Skip to content

Commit 30af42f

Browse files
committed
Add warning that curried function decl syntax is going away.
<rdar://problem/23111018>
1 parent 8c7c2e6 commit 30af42f

20 files changed

+106
-57
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,9 @@ ERROR(parameter_operator_keyword_argument,decl_parsing,none,
689689
ERROR(parameter_unnamed,decl_parsing,none,
690690
"unnamed parameters must be written with the empty name '_'", ())
691691

692+
WARNING(parameter_curry_syntax_removed,decl_parsing,none,
693+
"curried function declaration syntax will be removed in a future version of Swift; use a single parameter list", ())
694+
692695
//------------------------------------------------------------------------------
693696
// Statement parsing diagnostics
694697
//------------------------------------------------------------------------------

lib/Parse/ParsePattern.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ Parser::parseFunctionArguments(SmallVectorImpl<Identifier> &NamePieces,
563563
// Parse parameter-clauses.
564564
ParserStatus status;
565565
bool isFirstParameterClause = true;
566+
unsigned FirstBodyPatternIndex = BodyPatterns.size();
566567
while (Tok.is(tok::l_paren)) {
567568
SmallVector<ParsedParameter, 4> params;
568569
SourceLoc leftParenLoc, rightParenLoc;
@@ -583,6 +584,38 @@ Parser::parseFunctionArguments(SmallVectorImpl<Identifier> &NamePieces,
583584
paramContext = ParameterContextKind::Curried;
584585
}
585586

587+
// If the decl uses currying syntax, warn that that syntax is going away.
588+
if (BodyPatterns.size() - FirstBodyPatternIndex > 1) {
589+
SourceRange allPatternsRange(
590+
BodyPatterns[FirstBodyPatternIndex]->getStartLoc(),
591+
BodyPatterns.back()->getEndLoc());
592+
auto diag = diagnose(allPatternsRange.Start,
593+
diag::parameter_curry_syntax_removed);
594+
diag.highlight(allPatternsRange);
595+
bool seenArg = false;
596+
auto isEmptyPattern = [](Pattern *pattern) -> bool {
597+
auto *tuplePattern = dyn_cast<TuplePattern>(pattern);
598+
return tuplePattern && tuplePattern->getNumElements() == 0;
599+
};
600+
for (unsigned i = FirstBodyPatternIndex; i < BodyPatterns.size() - 1; i++) {
601+
// Replace ")(" with ", ", so "(x: Int)(y: Int)" becomes
602+
// "(x: Int, y: Int)". But just delete them if they're not actually
603+
// separating any arguments, e.g. in "()(y: Int)".
604+
StringRef replacement(", ");
605+
Pattern *leftPattern = BodyPatterns[i];
606+
Pattern *rightPattern = BodyPatterns[i + 1];
607+
if (!isEmptyPattern(leftPattern)) {
608+
seenArg = true;
609+
}
610+
if (!seenArg || isEmptyPattern(rightPattern)) {
611+
replacement = "";
612+
}
613+
diag.fixItReplace(SourceRange(leftPattern->getEndLoc(),
614+
rightPattern->getStartLoc()),
615+
replacement);
616+
}
617+
}
618+
586619
return status;
587620
}
588621

test/Constraints/diagnostics.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ func rdar21784170() {
261261
}
262262

263263
// <rdar://problem/21829141> BOGUS: unexpected trailing closure
264-
func expect<T, U>(_: T)(_: U.Type) {} // expected-note {{found this candidate}}
265-
func expect<T, U>(_: T, _: Int = 1)(_: U.Type) {} // expected-note {{found this candidate}}
264+
func expect<T, U>(_: T)(_: U.Type) {} // expected-note {{found this candidate}} expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
265+
func expect<T, U>(_: T, _: Int = 1)(_: U.Type) {} // expected-note {{found this candidate}} expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
266266
expect(Optional(3))(Optional<Int>.self) // expected-error {{ambiguous use of 'expect'}}
267267

268268
// <rdar://problem/19804707> Swift Enum Scoping Oddity
@@ -301,7 +301,7 @@ func r20789423() {
301301

302302

303303

304-
func f7(a: Int)(b : Int) -> Int {
304+
func f7(a: Int)(b : Int) -> Int { // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
305305
return a+b
306306
}
307307

@@ -317,7 +317,7 @@ f8(1.0) // expected-error {{cannot convert value of type 'Double' to exp
317317

318318
class CurriedClass {
319319
func method1() {}
320-
func method2(a: Int)(b : Int) {}
320+
func method2(a: Int)(b : Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
321321
func method3(a: Int, b : Int) {}
322322
}
323323

test/Constraints/members.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct Z {
4141
func getI() -> Int { return i }
4242
mutating func incI() {}
4343

44-
func curried(x: Int)(y: Int) -> Int { return x + y }
44+
func curried(x: Int)(y: Int) -> Int { return x + y } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
4545

4646
subscript (k : Int) -> Int {
4747
get {
@@ -110,7 +110,7 @@ enum W {
110110
case Omega
111111

112112
func foo(x: Int) {}
113-
func curried(x: Int)(y: Int) {}
113+
func curried(x: Int)(y: Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
114114
}
115115

116116
var w = W.Omega
@@ -326,7 +326,7 @@ protocol Functional {
326326
func apply(v: Vector) -> Scalar
327327
}
328328
protocol Coalgebra {
329-
func coproduct(f: Functional)(v1: Vector, v2: Vector) -> Scalar
329+
func coproduct(f: Functional)(v1: Vector, v2: Vector) -> Scalar // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
330330
}
331331

332332
// Make sure existential is closed early when we partially apply

test/Constraints/tuple.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ extension Int : PosixErrorReturn {
7272
}
7373

7474
func posixCantFail<A, T : protocol<Comparable, PosixErrorReturn>>
75-
(f:(A) -> T)(args:A) -> T
75+
(f:(A) -> T)(args:A) -> T // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
7676
{
7777
let result = f(args)
7878
assert(result != T.errorReturnValue())

test/Generics/same_type_constraints.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public struct LazySequenceOf<S : SequenceType, A where S.Generator.Element == A>
8484
public subscript(i : A) -> A { return i }
8585
}
8686

87-
public func iterate<A>(f : A -> A)(x : A) -> LazySequenceOf<Iterate<A>, A>? {
87+
public func iterate<A>(f : A -> A)(x : A) -> LazySequenceOf<Iterate<A>, A>? { // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
8888
return nil
8989
}
9090

test/IDE/print_ast_tc_decls.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,28 +173,28 @@ struct d0100_FooStruct {
173173
}
174174
// PASS_COMMON-NEXT: {{^}} subscript (i: Int, j: Int) -> Double { get }{{$}}
175175

176-
func curriedVoidFunc1()() {}
176+
func curriedVoidFunc1()() {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
177177
// PASS_COMMON-NEXT: {{^}} func curriedVoidFunc1()(){{$}}
178178

179-
func curriedVoidFunc2()(a: Int) {}
179+
func curriedVoidFunc2()(a: Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
180180
// PASS_COMMON-NEXT: {{^}} func curriedVoidFunc2()(a: Int){{$}}
181181

182-
func curriedVoidFunc3(a: Int)() {}
182+
func curriedVoidFunc3(a: Int)() {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
183183
// PASS_COMMON-NEXT: {{^}} func curriedVoidFunc3(a: Int)(){{$}}
184184

185-
func curriedVoidFunc4(a: Int)(b: Int) {}
185+
func curriedVoidFunc4(a: Int)(b: Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
186186
// PASS_COMMON-NEXT: {{^}} func curriedVoidFunc4(a: Int)(b: Int){{$}}
187187

188-
func curriedStringFunc1()() -> String { return "" }
188+
func curriedStringFunc1()() -> String { return "" } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
189189
// PASS_COMMON-NEXT: {{^}} func curriedStringFunc1()() -> String{{$}}
190190

191-
func curriedStringFunc2()(a: Int) -> String { return "" }
191+
func curriedStringFunc2()(a: Int) -> String { return "" } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
192192
// PASS_COMMON-NEXT: {{^}} func curriedStringFunc2()(a: Int) -> String{{$}}
193193

194-
func curriedStringFunc3(a: Int)() -> String { return "" }
194+
func curriedStringFunc3(a: Int)() -> String { return "" } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
195195
// PASS_COMMON-NEXT: {{^}} func curriedStringFunc3(a: Int)() -> String{{$}}
196196

197-
func curriedStringFunc4(a: Int)(b: Int) -> String { return "" }
197+
func curriedStringFunc4(a: Int)(b: Int) -> String { return "" } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
198198
// PASS_COMMON-NEXT: {{^}} func curriedStringFunc4(a: Int)(b: Int) -> String{{$}}
199199

200200
func bodyNameVoidFunc1(a: Int, b x: Float) {}

test/IDE/print_types.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func testVariadicFuncType(a: Int, b: Float...) {}
9999
// CHECK: FuncDecl '''testVariadicFuncType''' (Int, b: Float...) -> (){{$}}
100100
// FULL: FuncDecl '''testVariadicFuncType''' (Swift.Int, b: Swift.Float...) -> (){{$}}
101101

102-
func testCurriedFuncType1(a: Int)(b: Float) {}
102+
func testCurriedFuncType1(a: Int)(b: Float) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
103103
// CHECK: FuncDecl '''testCurriedFuncType1''' (Int) -> (b: Float) -> (){{$}}
104104
// FULL: FuncDecl '''testCurriedFuncType1''' (Swift.Int) -> (b: Swift.Float) -> (){{$}}
105105

test/SILPasses/mandatory_inlining.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func test_auto_closure_without_capture() -> Bool {
8080
// CHECK: [[FALSE:%.*]] = struct $Bool ([[FV:%.*]] : $Builtin.Int1)
8181
// CHECK: return [[FALSE]]
8282

83-
@transparent func test_curried(x: Int)(y: Int) -> Int {
83+
@transparent func test_curried(x: Int)(y: Int) -> Int { // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
8484
return y
8585
}
8686

test/attr/attr_objc.swift

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ protocol subject_containerProtocol1 {
241241

242242
@objc
243243
protocol subject_containerObjCProtocol1 {
244-
func func_Curried1()()
244+
func func_Curried1()() // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
245245
// expected-error@-1 {{method cannot be a member of an @objc protocol because curried functions cannot be represented in Objective-C}}
246246
// expected-note@-2 {{inferring '@objc' because the declaration is a member of an '@objc' protocol}}
247247

@@ -672,34 +672,34 @@ class infer_instanceFunc1 {
672672

673673
@objc func func_TupleStyle2a(a: Int, b: Int, c: Int) {}
674674

675-
func func_Curried1()() {}
675+
func func_Curried1()() {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
676676
// CHECK-LABEL: {{^}} func func_Curried1()() {
677677

678-
@objc func func_Curried1_()() {}
678+
@objc func func_Curried1_()() {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
679679
// expected-error@-1 {{method cannot be marked @objc because curried functions cannot be represented in Objective-C}}
680680

681-
func func_Curried2()(a: Int) {}
681+
func func_Curried2()(a: Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
682682
// CHECK-LABEL: {{^}} func func_Curried2()(a: Int) {
683683

684-
@objc func func_Curried2_()(a: Int) {}
684+
@objc func func_Curried2_()(a: Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
685685
// expected-error@-1 {{method cannot be marked @objc because curried functions cannot be represented in Objective-C}}
686686

687-
func func_Curried3()() -> Int {}
687+
func func_Curried3()() -> Int {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
688688
// CHECK-LABEL: {{^}} func func_Curried3()() -> Int {
689689

690-
@objc func func_Curried3_()() -> Int {}
690+
@objc func func_Curried3_()() -> Int {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
691691
// expected-error@-1 {{method cannot be marked @objc because curried functions cannot be represented in Objective-C}}
692692

693-
func func_Curried4()(a: String) {}
693+
func func_Curried4()(a: String) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
694694
// CHECK-LABEL: {{^}} func func_Curried4()(a: String) {
695695

696-
@objc func func_Curried4_()(a: String) {}
696+
@objc func func_Curried4_()(a: String) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
697697
// expected-error@-1 {{method cannot be marked @objc because curried functions cannot be represented in Objective-C}}
698698

699-
func func_Curried5()() -> String {}
699+
func func_Curried5()() -> String {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
700700
// CHECK-LABEL: {{^}} func func_Curried5()() -> String {
701701

702-
@objc func func_Curried5_()() -> String {}
702+
@objc func func_Curried5_()() -> String {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
703703
// expected-error@-1 {{method cannot be marked @objc because curried functions cannot be represented in Objective-C}}
704704

705705

@@ -1579,7 +1579,7 @@ class infer_class5 : Protocol_ObjC1 {}
15791579
protocol infer_protocol1 {
15801580
// CHECK-LABEL: {{^}}protocol infer_protocol1 {
15811581

1582-
func func_Curried1()() // no-error
1582+
func func_Curried1()() // no-error expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
15831583
// CHECK: {{^}} func func_Curried1()()
15841584

15851585
func nonObjC1()
@@ -1589,7 +1589,7 @@ protocol infer_protocol1 {
15891589
protocol infer_protocol2 : Protocol_Class1 {
15901590
// CHECK-LABEL: {{^}}protocol infer_protocol2 : Protocol_Class1 {
15911591

1592-
func func_Curried1()() // no-error
1592+
func func_Curried1()() // no-error expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
15931593
// CHECK: {{^}} func func_Curried1()()
15941594

15951595
func nonObjC1()
@@ -1599,7 +1599,7 @@ protocol infer_protocol2 : Protocol_Class1 {
15991599
protocol infer_protocol3 : Protocol_ObjC1 {
16001600
// CHECK-LABEL: {{^}}protocol infer_protocol3 : Protocol_ObjC1 {
16011601

1602-
func func_Curried1()() // no-error
1602+
func func_Curried1()() // no-error expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
16031603
// CHECK: {{^}} func func_Curried1()()
16041604

16051605
func nonObjC1()
@@ -1609,7 +1609,7 @@ protocol infer_protocol3 : Protocol_ObjC1 {
16091609
protocol infer_protocol4 : Protocol_Class1, Protocol_ObjC1 {
16101610
// CHECK-LABEL: {{^}}protocol infer_protocol4 : Protocol_Class1, Protocol_ObjC1 {
16111611

1612-
func func_Curried1()() // no-error
1612+
func func_Curried1()() // no-error expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
16131613
// CHECK: {{^}} func func_Curried1()()
16141614

16151615
func nonObjC1()
@@ -1619,7 +1619,7 @@ protocol infer_protocol4 : Protocol_Class1, Protocol_ObjC1 {
16191619
protocol infer_protocol5 : Protocol_ObjC1, Protocol_Class1 {
16201620
// CHECK-LABEL: {{^}}protocol infer_protocol5 : Protocol_ObjC1, Protocol_Class1 {
16211621

1622-
func func_Curried1()() // no-error
1622+
func func_Curried1()() // no-error expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
16231623
// CHECK: {{^}} func func_Curried1()()
16241624

16251625
func nonObjC1()

test/attr/attr_warn_unused_result.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class C1 {
2929
static func f2() { }
3030

3131
@warn_unused_result
32-
func curried1()()() { }
32+
func curried1()()() { } // expected-warning {{curried function declaration syntax will be removed in a future version of Swift}}
3333
}
3434

3535
func testMethodsNegative(c1: C1) {

test/attr/attributes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func foo(x: @convention(block) (Int) -> Int) {}
4949
@transparent
5050
func zim() {}
5151
@transparent
52-
func zang()() {}
52+
func zang()() {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
5353
@transparent
5454
func zung<T>(_: T) {}
5555
@transparent // expected-error{{@transparent cannot be applied to stored properties}} {{1-14=}}

test/decl/func/default-values.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func returnWithDefault() -> (a: Int, b: Int = 42) { // expected-error{{default a
2929

3030
// Only the first parameter list of a curried function can have a
3131
// default argument.
32-
func curried(i: Int = 1)
32+
func curried(i: Int = 1) // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
3333
(f : Float = 2) { // expected-error{{default argument is only permitted for a non-curried function parameter}}{{17-20=}}
3434
}
3535

test/decl/func/functions.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,16 @@ func var_inout_error(var inout x : Int) {} // expected-error {{parameter may not
141141
// Unnamed parameters require the name "_":
142142
func unnamed(Int) { } // expected-error{{unnamed parameters must be written with the empty name '_'}}{{14-14=_: }}
143143

144+
// Test fixits on curried functions.
145+
func testCurryFixits() {
146+
func f1(x: Int)(y: Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift; use a single parameter list}} {{17-19=, }}
147+
func f1a(x: Int, y: Int) {}
148+
func f2(x: Int)(y: Int)(z: Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift; use a single parameter list}} {{17-19=, }} {{25-27=, }}
149+
func f2a(x: Int, y: Int, z: Int) {}
150+
func f3(x: Int)() {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift; use a single parameter list}} {{17-19=}}
151+
func f3a(x: Int) {}
152+
func f4()(x: Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift; use a single parameter list}} {{11-13=}}
153+
func f4a(x: Int) {}
154+
func f5(x: Int)()(y: Int) {} // expected-warning{{curried function declaration syntax will be removed in a future version of Swift; use a single parameter list}} {{17-19=}} {{19-21=, }}
155+
func f5a(x: Int, y: Int) {}
156+
}

test/decl/func/keyword-argument-defaults.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ struct Subscripts2 {
6767
}
6868

6969

70-
func f4(a: Int)(_ b: Int) { }
71-
func f5(a: Int)(b: Int) { }
70+
func f4(a: Int)(_ b: Int) { } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
71+
func f5(a: Int)(b: Int) { } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
7272

7373
func testFunctions(i: Int, x: X) {
7474
f4(i)(i)
@@ -78,11 +78,11 @@ func testFunctions(i: Int, x: X) {
7878
}
7979

8080
struct Y {
81-
func m0(a: Int)(_ b: Int) { }
82-
func m1(a: Int)(b: Int) { }
81+
func m0(a: Int)(_ b: Int) { } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
82+
func m1(a: Int)(b: Int) { } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
8383

84-
func m2(a: Int)(_ b: Int, _ c: Int) { }
85-
func m3(a: Int)(b: Int, c2 c: Int) { }
84+
func m2(a: Int)(_ b: Int, _ c: Int) { } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
85+
func m3(a: Int)(b: Int, c2 c: Int) { } // expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
8686

8787
subscript (x: Int) -> Int {
8888
get { return x }
@@ -115,7 +115,7 @@ func testSubscripts(i: Int, s: String, x: Y) {
115115
func +(_ a: String, // expected-warning{{extraneous '_' in parameter: 'a' has no keyword argument name}}{{8-10=}}
116116
b b: Double) { } // expected-error{{operator cannot have keyword arguments}} {{8-10=}}
117117

118-
func +(a: Double, b: String)(_ c: Int)(d e: Int) { } // okay
118+
func +(a: Double, b: String)(_ c: Int)(d e: Int) { } // okay; expected-warning{{curried function declaration syntax will be removed in a future version of Swift}}
119119

120120
// # is being removed
121121
func pound(#a: Int, // expected-error{{'#' has been removed from Swift; double up 'a a' to make the argument label the same as the parameter name}}{{12-13=a }}

0 commit comments

Comments
 (0)