Skip to content

Commit a334c9f

Browse files
Fix usage of ParserForClass for case classes with more than 22 parameters with some default values in Scala 2.x (#123)
Somehow, the type annotation in the Scala 2 macro is necessary to avoid a compiler crash for large case classes which use default values, due to some issue with type inference: the lambda we generate that wraps a call to the default parameter method gets its type inferred as `<error>` after the `uncurry` phase. Not sure exactly what is the cause, but providing an explicit type annotation to the return value of the lambda seems to work around the problem PR contains a repro and unit test
1 parent a780800 commit a334c9f

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

mainargs/src-2/Macros.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,13 @@ class Macros(val c: Context) {
9696

9797
val argListSymbol = q"${c.fresh[TermName](TermName("argsList"))}"
9898

99-
val defaults = for ((arg, i) <- flattenedArgLists.zipWithIndex) yield {
99+
val defaults = for ((arg0, i) <- flattenedArgLists.zipWithIndex) yield {
100100
val arg = TermName(c.freshName())
101-
hasDefault(i).map(defaultName =>
102-
q"($arg: $curCls) => $arg.${newTermName(defaultName)}"
103-
)
101+
hasDefault(i) match{
102+
case None => q"_root_.scala.None"
103+
case Some(defaultName) =>
104+
q"_root_.scala.Some[$curCls => ${arg0.info}](($arg: $curCls) => $arg.${newTermName(defaultName)}: ${arg0.info})"
105+
}
104106
}
105107

106108
val argSigs = for ((arg, defaultOpt) <- flattenedArgLists.zip(defaults)) yield {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package mainargs
2+
import utest._
3+
@main
4+
case class LargeArgs(
5+
v1: String,
6+
v2: String = "v2-default",
7+
v3: Option[String] = None,
8+
v4: Option[String] = None,
9+
v5: Int,
10+
v6: Int = 0,
11+
v7: Int = 123,
12+
v8: Int = 3.14.toInt,
13+
v9: Boolean,
14+
v10: Boolean = true,
15+
v11: Boolean = false,
16+
v12: Option[Int] = None,
17+
v13: Option[Int] = None,
18+
v14: String = "v14-default",
19+
v15: String = "v15-default",
20+
v16: String = "v16-default",
21+
v17: String = "v17-default",
22+
v18: String = "v18-default",
23+
v19: String = "v19-default",
24+
v20: String = "v20-default",
25+
v21: String = "v21-default",
26+
v22: String = "v22-default",
27+
v23: String = "v23-default",
28+
v24: String = "v24-default",
29+
v25: String = "v25-default",
30+
v26: String = "v26-default",
31+
v27: String = "v27-default",
32+
v28: String = "v28-default",
33+
v29: String = "v29-default",
34+
v30: String = "v30-default",
35+
v31: String = "v31-default",
36+
v32: String = "v32-default",
37+
)
38+
39+
object LargeClassTests extends TestSuite{
40+
val largeArgsParser = ParserForClass[LargeArgs]
41+
42+
val tests = Tests {
43+
test("simple") {
44+
largeArgsParser.constructOrThrow(
45+
Seq("--v1", "v1-value", "--v5", "5", "--v9", "true", "--v23", "v23-value")
46+
) ==>
47+
LargeArgs(v1 = "v1-value", v5 = 5, v9 = true, v23 = "v23-value")
48+
}
49+
}
50+
}

readme.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,10 @@ command-line friendly tool.
625625

626626
# Changelog
627627

628+
## master
629+
630+
- Fix usage of `ParserForClass` for `case class`es with more than 22 parameters in Scala 2.x
631+
628632
## 0.6.2
629633

630634
- Make combine short args that fail to parse go through normal leftover-token code paths

0 commit comments

Comments
 (0)