summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-07-02 01:01:44 +0000
committerPaul Phillips <paulp@improving.org>2010-07-02 01:01:44 +0000
commit57b7e442af26e07dc2411f46b0a8103dfe054101 (patch)
treefa27f49579d3e2a62781af86f148eb1d4f33fcce
parent9421f2ecaf85cb2e409e73dad7554e466303c284 (diff)
downloadscala-57b7e442af26e07dc2411f46b0a8103dfe054101.tar.gz
scala-57b7e442af26e07dc2411f46b0a8103dfe054101.tar.bz2
scala-57b7e442af26e07dc2411f46b0a8103dfe054101.zip
Fail more gracefully on > 22 case class paramet...
Fail more gracefully on > 22 case class parameters. Closes #3631, no review.
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala7
-rw-r--r--test/files/neg/bug3631.check4
-rw-r--r--test/files/neg/bug3631.scala3
5 files changed, 26 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index f21b1b20ff..46ddf7b24b 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -151,6 +151,12 @@ abstract class TreeInfo {
case _ :: stats1 => firstConstructor(stats1)
}
+ /** The arguments to the first constructor in `stats'. */
+ def firstConstructorArgs(stats: List[Tree]): List[Tree] = firstConstructor(stats) match {
+ case DefDef(_, _, _, args :: _, _, _) => args
+ case _ => Nil
+ }
+
/** The value definitions marked PRESUPER in this statement sequence */
def preSuperFields(stats: List[Tree]): List[ValDef] =
for (vdef @ ValDef(mods, _, _, _) <- stats if mods hasFlag PRESUPER) yield vdef
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index d56b8ed944..2123a00550 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -287,13 +287,11 @@ trait Namers { self: Analyzer =>
* class definition tree.
* @return the companion object symbol.
*/
- def ensureCompanionObject(tree: ClassDef, creator: => Tree): Symbol = {
- val m: Symbol = context.scope.lookup(tree.name.toTermName).filter(! _.isSourceMethod)
- if (m.isModule && inCurrentScope(m) && currentRun.compiles(m)) m
- else
- /*util.trace("enter synthetic companion object for "+currentRun.compiles(m)+":")*/(
- enterSyntheticSym(creator))
- }
+ def ensureCompanionObject(tree: ClassDef, creator: => Tree): Symbol = {
+ val m: Symbol = context.scope.lookup(tree.name.toTermName).filter(! _.isSourceMethod)
+ if (m.isModule && inCurrentScope(m) && currentRun.compiles(m)) m
+ else enterSyntheticSym(creator)
+ }
private def enterSymFinishWith(tree: Tree, tparams: List[TypeDef]) {
val sym = tree.symbol
@@ -350,6 +348,9 @@ trait Namers { self: Analyzer =>
tree.symbol = enterClassSymbol(tree)
finishWith(tparams)
if (mods.isCase) {
+ if (treeInfo.firstConstructorArgs(impl.body).size > MaxFunctionArity)
+ context.error(tree.pos, "Implementation restriction: case classes cannot have more than " + MaxFunctionArity + " parameters.")
+
val m = ensureCompanionObject(tree, caseModuleDef(tree))
caseClassOfModuleClass(m.moduleClass) = tree
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index c3631f0d05..735cb4a3c4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -133,8 +133,11 @@ trait Unapplies extends ast.TreeDSL
/** The module corresponding to a case class; overrides toString to show the module's name
*/
def caseModuleDef(cdef: ClassDef): ModuleDef = {
- def inheritFromFun = !(cdef.mods hasFlag ABSTRACT) && cdef.tparams.isEmpty && constrParamss(cdef).length == 1
- def createFun = gen.scalaFunctionConstr(constrParamss(cdef).head map (_.tpt), toIdent(cdef), abstractFun = true)
+ // > MaxFunctionArity is caught in Namers, but for nice error reporting instead of
+ // an abrupt crash we trim the list here.
+ def primaries = constrParamss(cdef).head take MaxFunctionArity map (_.tpt)
+ def inheritFromFun = !cdef.mods.isAbstract && cdef.tparams.isEmpty && constrParamss(cdef).length == 1
+ def createFun = gen.scalaFunctionConstr(primaries, toIdent(cdef), abstractFun = true)
def parents = if (inheritFromFun) List(createFun) else Nil
def toString = DefDef(
Modifiers(OVERRIDE | FINAL),
diff --git a/test/files/neg/bug3631.check b/test/files/neg/bug3631.check
new file mode 100644
index 0000000000..12d94aa4dc
--- /dev/null
+++ b/test/files/neg/bug3631.check
@@ -0,0 +1,4 @@
+bug3631.scala:3: error: Implementation restriction: case classes cannot have more than 22 parameters.
+case class X23(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int) { }
+ ^
+one error found
diff --git a/test/files/neg/bug3631.scala b/test/files/neg/bug3631.scala
new file mode 100644
index 0000000000..bcf91619ee
--- /dev/null
+++ b/test/files/neg/bug3631.scala
@@ -0,0 +1,3 @@
+case class X22(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int) { }
+
+case class X23(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int) { } \ No newline at end of file