diff options
author | Paul Phillips <paulp@improving.org> | 2010-07-02 01:01:44 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-07-02 01:01:44 +0000 |
commit | 57b7e442af26e07dc2411f46b0a8103dfe054101 (patch) | |
tree | fa27f49579d3e2a62781af86f148eb1d4f33fcce | |
parent | 9421f2ecaf85cb2e409e73dad7554e466303c284 (diff) | |
download | scala-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.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 15 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Unapplies.scala | 7 | ||||
-rw-r--r-- | test/files/neg/bug3631.check | 4 | ||||
-rw-r--r-- | test/files/neg/bug3631.scala | 3 |
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 |