Skip to content

Commit ae03df9

Browse files
committed
Merge pull request scala#5147 from som-snytt/issue/8667-too-many-args
SI-8667 Improve too-many-args message
2 parents 5fffe79 + 40b42ae commit ae03df9

15 files changed

+219
-50
lines changed

src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -539,8 +539,43 @@ trait ContextErrors {
539539
def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) =
540540
NormalTypeError(tree, "macro applications do not support named and/or default arguments")
541541

542-
def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) =
543-
NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun))
542+
def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree, formals: List[Type], args: List[Tree], namelessArgs: List[Tree], argPos: Array[Int]) = {
543+
val expected = formals.size
544+
val supplied = args.size
545+
// pick a caret. For f(k=1,i=2,j=3), argPos[0,-1,1] b/c `k=1` taken as arg0
546+
val excessive = {
547+
val i = argPos.indexWhere(_ >= expected)
548+
if (i < 0) tree else args(i min (supplied - 1))
549+
}
550+
val msg = {
551+
val badappl = {
552+
val excess = supplied - expected
553+
val target = treeSymTypeMsg(fun)
554+
555+
if (expected == 0) s"no arguments allowed for nullary $target"
556+
else if (excess < 3 && expected <= 5) s"too many arguments ($supplied) for $target"
557+
else if (expected > 10) s"$supplied arguments but expected $expected for $target"
558+
else {
559+
val more =
560+
if (excess == 1) "one more argument"
561+
else if (excess > 0) s"$excess more arguments"
562+
else "too many arguments"
563+
s"$more than can be applied to $target"
564+
}
565+
}
566+
val unknowns = (namelessArgs zip args) collect {
567+
case (_: Assign, AssignOrNamedArg(Ident(name), _)) => name
568+
}
569+
val suppl =
570+
unknowns.size match {
571+
case 0 => ""
572+
case 1 => s"\nNote that '${unknowns.head}' is not a parameter name of the invoked method."
573+
case _ => unknowns.mkString("\nNote that '", "', '", "' are not parameter names of the invoked method.")
574+
}
575+
s"${badappl}${suppl}"
576+
}
577+
NormalTypeError(excessive, msg)
578+
}
544579

545580
// can it still happen? see test case neg/overloaded-unapply.scala
546581
def OverloadedUnapplyError(tree: Tree) =
@@ -552,7 +587,7 @@ trait ContextErrors {
552587
def MultipleVarargError(tree: Tree) =
553588
NormalTypeError(tree, "when using named arguments, the vararg parameter has to be specified exactly once")
554589

555-
def ModuleUsingCompanionClassDefaultArgsErrror(tree: Tree) =
590+
def ModuleUsingCompanionClassDefaultArgsError(tree: Tree) =
556591
NormalTypeError(tree, "module extending its companion class cannot use default constructor arguments")
557592

558593
def NotEnoughArgsError(tree: Tree, fun: Tree, missing: List[Symbol]) = {

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3337,7 +3337,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
33373337
// #2064
33383338
duplErrorTree(WrongNumberOfArgsError(tree, fun))
33393339
} else if (lencmp > 0) {
3340-
tryTupleApply orElse duplErrorTree(TooManyArgsNamesDefaultsError(tree, fun))
3340+
tryTupleApply orElse duplErrorTree {
3341+
val (namelessArgs, argPos) = removeNames(Typer.this)(args, params)
3342+
TooManyArgsNamesDefaultsError(tree, fun, formals, args, namelessArgs, argPos)
3343+
}
33413344
} else if (lencmp == 0) {
33423345
// we don't need defaults. names were used, so this application is transformed
33433346
// into a block (@see transformNamedApplication in NamesDefaults)
@@ -3401,7 +3404,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
34013404
val lencmp2 = compareLengths(allArgs, formals)
34023405

34033406
if (!sameLength(allArgs, args) && callToCompanionConstr(context, funSym)) {
3404-
duplErrorTree(ModuleUsingCompanionClassDefaultArgsErrror(tree))
3407+
duplErrorTree(ModuleUsingCompanionClassDefaultArgsError(tree))
34053408
} else if (lencmp2 > 0) {
34063409
removeNames(Typer.this)(allArgs, params) // #3818
34073410
duplErrTree

test/files/neg/eta-expand-star.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
eta-expand-star.scala:6: error: too many arguments for method apply: (v1: Seq[T])Unit in trait Function1
1+
eta-expand-star.scala:6: error: too many arguments (2) for method apply: (v1: Seq[T])Unit in trait Function1
22
g(1, 2)
3-
^
3+
^
44
one error found

test/files/neg/macro-invalidusage-badargs.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Macros_Test_2.scala:8: error: not enough arguments for macro method foo: (x: Int
1313
Unspecified value parameter x.
1414
foo()
1515
^
16-
Macros_Test_2.scala:9: error: too many arguments for macro method foo: (x: Int)Int
16+
Macros_Test_2.scala:9: error: too many arguments (2) for macro method foo: (x: Int)Int
1717
foo(4, 2)
18-
^
18+
^
1919
5 errors found

test/files/neg/multi-array.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
multi-array.scala:7: error: too many arguments for constructor Array: (_length: Int)Array[T]
1+
multi-array.scala:7: error: too many arguments (2) for constructor Array: (_length: Int)Array[T]
22
val a: Array[Int] = new Array(10, 10)
3-
^
3+
^
44
one error found

test/files/neg/protected-constructors.check

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
protected-constructors.scala:17: error: too many arguments for constructor Foo1: ()dingus.Foo1
1+
protected-constructors.scala:17: error: no arguments allowed for nullary constructor Foo1: ()dingus.Foo1
22
val foo1 = new Foo1("abc")
3-
^
3+
^
44
protected-constructors.scala:18: error: constructor Foo2 in class Foo2 cannot be accessed in object P
55
Access to protected constructor Foo2 not permitted because
66
enclosing object P in package hungus is not a subclass of
@@ -19,4 +19,7 @@ protected-constructors.scala:15: error: class Foo3 in object Ding cannot be acce
1919
object Ding in package dingus where target is defined
2020
class Bar3 extends Ding.Foo3("abc")
2121
^
22-
four errors found
22+
protected-constructors.scala:15: error: no arguments allowed for nullary constructor Object: ()Object
23+
class Bar3 extends Ding.Foo3("abc")
24+
^
25+
5 errors found

test/files/neg/t1112.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
t1112.scala:12: error: too many arguments for method call: (p: Int)(f: => Test.this.Type1)Unit
1+
t1112.scala:12: error: too many arguments (2) for method call: (p: Int)(f: => Test.this.Type1)Unit
22
call(0,() => System.out.println("here we are"))
3-
^
3+
^
44
one error found

test/files/neg/t1523.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
t1523.scala:4: error: too many arguments for method bug: (x: Any)Any
1+
t1523.scala:4: error: 25 more arguments than can be applied to method bug: (x: Any)Any
22
def go() = bug("a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a")
3-
^
3+
^
44
one error found

test/files/neg/t6920.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
t6920.scala:9: error: too many arguments for method applyDynamicNamed: (values: Seq[(String, Any)])String
1+
t6920.scala:9: error: too many arguments (2) for method applyDynamicNamed: (values: Seq[(String, Any)])String
22
error after rewriting to CompilerError.this.test.applyDynamicNamed("crushTheCompiler")(scala.Tuple2("a", 1), scala.Tuple2("b", 2))
33
possible cause: maybe a wrong Dynamic method signature?
44
test.crushTheCompiler(a = 1, b = 2)
5-
^
5+
^
66
one error found

test/files/neg/t7157.check

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
Test_2.scala:5: error: too many arguments for macro method m1_0_0: ()Unit
1+
Test_2.scala:5: error: no arguments allowed for nullary macro method m1_0_0: ()Unit
22
m1_0_0(1)
3-
^
4-
Test_2.scala:6: error: too many arguments for macro method m1_0_0: ()Unit
3+
^
4+
Test_2.scala:6: error: no arguments allowed for nullary macro method m1_0_0: ()Unit
55
m1_0_0(1, 2)
6-
^
7-
Test_2.scala:7: error: too many arguments for macro method m1_0_0: ()Unit
6+
^
7+
Test_2.scala:7: error: no arguments allowed for nullary macro method m1_0_0: ()Unit
88
m1_0_0(1, 2, 3)
9-
^
9+
^
1010
Test_2.scala:9: error: not enough arguments for macro method m1_1_1: (x: Int)Unit.
1111
Unspecified value parameter x.
1212
m1_1_1()
1313
^
14-
Test_2.scala:11: error: too many arguments for macro method m1_1_1: (x: Int)Unit
14+
Test_2.scala:11: error: too many arguments (2) for macro method m1_1_1: (x: Int)Unit
1515
m1_1_1(1, 2)
16-
^
17-
Test_2.scala:12: error: too many arguments for macro method m1_1_1: (x: Int)Unit
16+
^
17+
Test_2.scala:12: error: too many arguments (3) for macro method m1_1_1: (x: Int)Unit
1818
m1_1_1(1, 2, 3)
19-
^
19+
^
2020
Test_2.scala:14: error: not enough arguments for macro method m1_2_2: (x: Int, y: Int)Unit.
2121
Unspecified value parameters x, y.
2222
m1_2_2()
@@ -25,9 +25,9 @@ Test_2.scala:15: error: not enough arguments for macro method m1_2_2: (x: Int, y
2525
Unspecified value parameter y.
2626
m1_2_2(1)
2727
^
28-
Test_2.scala:17: error: too many arguments for macro method m1_2_2: (x: Int, y: Int)Unit
28+
Test_2.scala:17: error: too many arguments (3) for macro method m1_2_2: (x: Int, y: Int)Unit
2929
m1_2_2(1, 2, 3)
30-
^
30+
^
3131
Test_2.scala:24: error: not enough arguments for macro method m1_1_inf: (x: Int, y: Int*)Unit.
3232
Unspecified value parameters x, y.
3333
m1_1_inf()
@@ -40,25 +40,25 @@ Test_2.scala:30: error: not enough arguments for macro method m1_2_inf: (x: Int,
4040
Unspecified value parameters y, z.
4141
m1_2_inf(1)
4242
^
43-
Test_2.scala:35: error: too many arguments for macro method m2_0_0: ()Unit
43+
Test_2.scala:35: error: no arguments allowed for nullary macro method m2_0_0: ()Unit
4444
m2_0_0()(1)
45-
^
46-
Test_2.scala:36: error: too many arguments for macro method m2_0_0: ()Unit
45+
^
46+
Test_2.scala:36: error: no arguments allowed for nullary macro method m2_0_0: ()Unit
4747
m2_0_0()(1, 2)
48-
^
49-
Test_2.scala:37: error: too many arguments for macro method m2_0_0: ()Unit
48+
^
49+
Test_2.scala:37: error: no arguments allowed for nullary macro method m2_0_0: ()Unit
5050
m2_0_0()(1, 2, 3)
51-
^
51+
^
5252
Test_2.scala:39: error: not enough arguments for macro method m2_1_1: (x: Int)Unit.
5353
Unspecified value parameter x.
5454
m2_1_1()()
5555
^
56-
Test_2.scala:41: error: too many arguments for macro method m2_1_1: (x: Int)Unit
56+
Test_2.scala:41: error: too many arguments (2) for macro method m2_1_1: (x: Int)Unit
5757
m2_1_1()(1, 2)
58-
^
59-
Test_2.scala:42: error: too many arguments for macro method m2_1_1: (x: Int)Unit
58+
^
59+
Test_2.scala:42: error: too many arguments (3) for macro method m2_1_1: (x: Int)Unit
6060
m2_1_1()(1, 2, 3)
61-
^
61+
^
6262
Test_2.scala:44: error: not enough arguments for macro method m2_2_2: (x: Int, y: Int)Unit.
6363
Unspecified value parameters x, y.
6464
m2_2_2()()
@@ -67,9 +67,9 @@ Test_2.scala:45: error: not enough arguments for macro method m2_2_2: (x: Int, y
6767
Unspecified value parameter y.
6868
m2_2_2()(1)
6969
^
70-
Test_2.scala:47: error: too many arguments for macro method m2_2_2: (x: Int, y: Int)Unit
70+
Test_2.scala:47: error: too many arguments (3) for macro method m2_2_2: (x: Int, y: Int)Unit
7171
m2_2_2()(1, 2, 3)
72-
^
72+
^
7373
Test_2.scala:54: error: not enough arguments for macro method m2_1_inf: (x: Int, y: Int*)Unit.
7474
Unspecified value parameters x, y.
7575
m2_1_inf()()

test/files/neg/t8006.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
t8006.scala:3: error: too many arguments for method applyDynamicNamed: (value: (String, Any))String
1+
t8006.scala:3: error: too many arguments (2) for method applyDynamicNamed: (value: (String, Any))String
22
error after rewriting to X.this.d.applyDynamicNamed("meth")(scala.Tuple2("value1", 10), scala.Tuple2("value2", 100))
33
possible cause: maybe a wrong Dynamic method signature?
44
d.meth(value1 = 10, value2 = 100) // two arguments here, but only one is allowed
5-
^
5+
^
66
one error found

test/files/neg/t8035-no-adapted-args.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ t8035-no-adapted-args.scala:4: warning: No automatic adaptation here: use explic
44
after adaptation: Test.f((1, 2, 3): (Int, Int, Int))
55
f(1, 2, 3)
66
^
7-
t8035-no-adapted-args.scala:4: error: too many arguments for method f: (x: (Int, Int, Int))Int
7+
t8035-no-adapted-args.scala:4: error: too many arguments (3) for method f: (x: (Int, Int, Int))Int
88
f(1, 2, 3)
9-
^
9+
^
1010
t8035-no-adapted-args.scala:5: warning: No automatic adaptation here: use explicit parentheses.
1111
signature: Test.f[T](x: T): Int
1212
given arguments: <none>

test/files/neg/t8667.check

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
t8667.scala:6: error: too many arguments (3) for constructor C: (a: Int, b: Int)C
2+
Note that 'c' is not a parameter name of the invoked method.
3+
def c2 = new C(a = 42, b = 17, c = 5)
4+
^
5+
t8667.scala:7: error: unknown parameter name: c
6+
def c3 = new C(b = 42, a = 17, c = 5)
7+
^
8+
t8667.scala:7: error: too many arguments (3) for constructor C: (a: Int, b: Int)C
9+
def c3 = new C(b = 42, a = 17, c = 5)
10+
^
11+
t8667.scala:8: error: positional after named argument.
12+
def c4 = new C(b = 42, a = 17, 5)
13+
^
14+
t8667.scala:8: error: too many arguments (3) for constructor C: (a: Int, b: Int)C
15+
def c4 = new C(b = 42, a = 17, 5)
16+
^
17+
t8667.scala:9: error: not found: value c
18+
def c5 = new C(a = 42, c = 17)
19+
^
20+
t8667.scala:10: error: parameter 'b' is already specified at parameter position 2
21+
Note that 'c' is not a parameter name of the invoked method.
22+
def c6 = new C(a = 42, c = 17, b = 5)
23+
^
24+
t8667.scala:10: error: too many arguments (3) for constructor C: (a: Int, b: Int)C
25+
Note that 'c' is not a parameter name of the invoked method.
26+
def c6 = new C(a = 42, c = 17, b = 5)
27+
^
28+
t8667.scala:11: error: parameter 'a' is already specified at parameter position 1
29+
Note that 'c' is not a parameter name of the invoked method.
30+
def c7 = new C(c = 42, a = 17, b = 5)
31+
^
32+
t8667.scala:11: error: too many arguments (3) for constructor C: (a: Int, b: Int)C
33+
Note that 'c' is not a parameter name of the invoked method.
34+
def c7 = new C(c = 42, a = 17, b = 5)
35+
^
36+
t8667.scala:12: error: parameter 'b' is already specified at parameter position 2
37+
def c8 = new C(42, 17, b = 5)
38+
^
39+
t8667.scala:12: error: too many arguments (3) for constructor C: (a: Int, b: Int)C
40+
def c8 = new C(42, 17, b = 5)
41+
^
42+
t8667.scala:13: error: parameter 'b' is already specified at parameter position 2
43+
Note that 'c' is not a parameter name of the invoked method.
44+
def c9 = new C(a = 42, c = 17, d = 3, b = 5)
45+
^
46+
t8667.scala:13: error: too many arguments (4) for constructor C: (a: Int, b: Int)C
47+
Note that 'c', 'd' are not parameter names of the invoked method.
48+
def c9 = new C(a = 42, c = 17, d = 3, b = 5)
49+
^
50+
t8667.scala:14: error: too many arguments (4) for constructor C: (a: Int, b: Int)C
51+
Note that 'd', 'c' are not parameter names of the invoked method.
52+
def c0 = new C(42, 17, d = 3, c = 5)
53+
^
54+
t8667.scala:25: error: no arguments allowed for nullary method f0: ()Int
55+
f0(1)
56+
^
57+
t8667.scala:26: error: too many arguments (2) for method f1: (i: Int)Int
58+
f1(1, 2)
59+
^
60+
t8667.scala:27: error: too many arguments (3) for method f1: (i: Int)Int
61+
f1(1, 2, 3)
62+
^
63+
t8667.scala:28: error: 3 more arguments than can be applied to method f1: (i: Int)Int
64+
f1(1, 2, 3, 4)
65+
^
66+
t8667.scala:29: error: 3 more arguments than can be applied to method f1: (i: Int)Int
67+
Note that 'j' is not a parameter name of the invoked method.
68+
f1(1, j = 2, 3, 4)
69+
^
70+
t8667.scala:30: error: 3 more arguments than can be applied to method f1: (i: Int)Int
71+
Note that 'j', 'k' are not parameter names of the invoked method.
72+
f1(1, j = 2, k = 3, 4)
73+
^
74+
t8667.scala:31: error: parameter 'i' is already specified at parameter position 1
75+
Note that 'k' is not a parameter name of the invoked method.
76+
f2(k = 1, i = 2, j = 3)
77+
^
78+
t8667.scala:31: error: too many arguments (3) for method f2: (i: Int, j: Int)Int
79+
Note that 'k' is not a parameter name of the invoked method.
80+
f2(k = 1, i = 2, j = 3)
81+
^
82+
t8667.scala:32: error: one more argument than can be applied to method f6: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int)Int
83+
f6(1, 2, 3, 4, 5, 6, 7)
84+
^
85+
t8667.scala:33: error: 2 more arguments than can be applied to method f6: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int)Int
86+
f6(1, 2, 3, 4, 5, 6, 7, 8)
87+
^
88+
t8667.scala:34: error: 15 arguments but expected 12 for method f12: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int, o: Int, p: Int, q: Int, r: Int, s: Int, t: Int)Int
89+
f12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
90+
^
91+
26 errors found

test/files/neg/t8667.scala

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
class C(a: Int, b: Int)
3+
4+
trait T {
5+
def c1 = new C(a = 42, b = 17)
6+
def c2 = new C(a = 42, b = 17, c = 5)
7+
def c3 = new C(b = 42, a = 17, c = 5)
8+
def c4 = new C(b = 42, a = 17, 5)
9+
def c5 = new C(a = 42, c = 17)
10+
def c6 = new C(a = 42, c = 17, b = 5)
11+
def c7 = new C(c = 42, a = 17, b = 5)
12+
def c8 = new C(42, 17, b = 5)
13+
def c9 = new C(a = 42, c = 17, d = 3, b = 5)
14+
def c0 = new C(42, 17, d = 3, c = 5)
15+
}
16+
17+
trait X {
18+
def f0() = 42
19+
def f1(i: Int) = 42
20+
def f2(i: Int, j: Int) = 42
21+
def f6(i: Int, j: Int, k: Int, l: Int, m: Int, n: Int) = 42
22+
def f12(i: Int, j: Int, k: Int, l: Int, m: Int, n: Int, o: Int, p: Int, q: Int, r: Int, s: Int, t: Int) = 42
23+
24+
def g() = {
25+
f0(1)
26+
f1(1, 2)
27+
f1(1, 2, 3)
28+
f1(1, 2, 3, 4)
29+
f1(1, j = 2, 3, 4)
30+
f1(1, j = 2, k = 3, 4)
31+
f2(k = 1, i = 2, j = 3)
32+
f6(1, 2, 3, 4, 5, 6, 7)
33+
f6(1, 2, 3, 4, 5, 6, 7, 8)
34+
f12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
35+
()
36+
}
37+
}

test/files/neg/t876.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
t876.scala:25: error: too many arguments for method apply: (key: AssertionError.A)manager.B in class HashMap
1+
t876.scala:25: error: too many arguments (2) for method apply: (key: AssertionError.A)manager.B in class HashMap
22
assert(manager.map(A2) == List(manager.map(A2, A1)))
3-
^
3+
^
44
one error found

0 commit comments

Comments
 (0)