diff options
author | Martin Odersky <odersky@gmail.com> | 2007-01-10 19:24:14 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2007-01-10 19:24:14 +0000 |
commit | d1d980fd2b51304c504bff2529378a31b1ad91e9 (patch) | |
tree | cbe3e64fe35e157625c46fde06a3873a7aa50135 | |
parent | 181cefa87219f65d9b6d101049d4916db6715092 (diff) | |
download | scala-d1d980fd2b51304c504bff2529378a31b1ad91e9.tar.gz scala-d1d980fd2b51304c504bff2529378a31b1ad91e9.tar.bz2 scala-d1d980fd2b51304c504bff2529378a31b1ad91e9.zip |
fixed bug877
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/Trees.scala | 23 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 50 | ||||
-rw-r--r-- | test/files/neg/bug877.check | 2 |
4 files changed, 55 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 230665f96e..2ca8fc057d 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -163,20 +163,19 @@ trait Trees requires Global { override val copy = new StrictTreeCopier } - private def syntheticParams(owner: Symbol, formals: List[Type]): List[Symbol] = { + private def syntheticParams(owner: Symbol, mtp: Type): List[List[Symbol]] = { var cnt = 0 def freshName() = { cnt = cnt + 1; newTermName("x$" + cnt) } - for (val formal <- formals) yield - owner.newValueParameter(owner.pos, freshName()).setInfo(formal) - } - - private def syntheticParams(owner: Symbol, mtp: Type): List[List[Symbol]] = mtp match { - case PolyType(_, restp) => - syntheticParams(owner, restp) - case MethodType(formals, restp) => - syntheticParams(owner, formals) :: syntheticParams(owner, restp) - case _ => - List() + def synthetics(mtp: Type): List[List[Symbol]] = mtp match { + case PolyType(_, restp) => + synthetics(restp) + case MethodType(formals, restp) => + (formals map (f => owner.newValueParameter(owner.pos, freshName()).setInfo(f))) :: + synthetics(restp) + case _ => + List() + } + synthetics(mtp) } // def nextPhase = if (phase.id > globalPhase.id) phase else phase.next; diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 454264c61c..c5892b79fb 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -815,6 +815,10 @@ trait Symbols requires SymbolTable { final def setter(base: Symbol): Symbol = base.info.decl(nme.getterToSetter(nme.getterName(name))) filter (.hasFlag(ACCESSOR)) + /** The case factory corresponding to this case class */ + final def caseFactory: Symbol = + owner.info.decl(name.toTermName).suchThat(.isCaseFactory) + /** If this symbol is a skolem, its corresponding type parameter, otherwise this */ def deSkolemize: Symbol = this diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 648002ed9d..62d2185600 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -430,6 +430,20 @@ abstract class RefChecks extends InfoTransform { // Transformation ------------------------------------------------------------ + /* Convert a reference to a case factory of type `tpe' to a new of the class it produces. */ + def toConstructor(pos: PositionType, tpe: Type): Tree = { + var rtpe = tpe.finalResultType + assert(rtpe.symbol hasFlag CASE, tpe); + localTyper.typedOperator { + atPos(pos) { + Select(New(TypeTree(rtpe)), rtpe.symbol.primaryConstructor) + } + } + } + + def isConcreteLocalCaseFactory(clazz: Symbol) = + (clazz hasFlag CASE) && !(clazz hasFlag ABSTRACT) && !(clazz.owner hasFlag PACKAGE) + override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { pushLevel() enterSyms(stats) @@ -467,6 +481,28 @@ abstract class RefChecks extends InfoTransform { else transformTrees(List(cdef, vdef, ddef)) } + case ClassDef(_, _, _, _, _) if isConcreteLocalCaseFactory(tree.symbol) => + val clazz = tree.symbol + val factory = clazz.caseFactory + assert(factory != NoSymbol, clazz) + def mkArgument(vparam: Symbol) = { + val id = Ident(vparam) + if (vparam.tpe.symbol == RepeatedParamClass) Typed(id, Ident(nme.WILDCARD_STAR.toTypeName)) + else id + } + val caseFactoryDef = + localTyper.typed { + atPos(tree.pos) { + DefDef( + factory, + vparamss => + (toConstructor(tree.pos, factory.tpe) /: vparamss) { + (fn, vparams) => Apply(fn, vparams map mkArgument) + }) + } + } + List(transform(tree), caseFactoryDef) + case ValDef(_, _, _, _) => val tree1 = transform(tree); // important to do before forward reference check if (tree.symbol.isLocal && index <= currentLevel.maxindex) { @@ -484,14 +520,6 @@ abstract class RefChecks extends InfoTransform { override def transform(tree: Tree): Tree = try { - /* Convert a reference of a case factory to a new of the class it produces. */ - def toConstructor: Tree = { - var tpe = tree.tpe - while (!tpe.symbol.isClass) tpe = tpe.resultType; - assert(tpe.symbol hasFlag CASE); - typedOperator(atPos(tree.pos)(Select(New(TypeTree(tpe)), tpe.symbol.primaryConstructor))); - } - /* Check whether argument types conform to bounds of type parameters */ def checkBounds(tparams: List[Symbol], argtps: List[Type]): unit = try { typer.infer.checkBounds(tree.pos, tparams, argtps, ""); @@ -556,7 +584,7 @@ abstract class RefChecks extends InfoTransform { case TypeApply(fn, args) => checkBounds(fn.tpe.typeParams, args map (.tpe)) - if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor; + if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor(tree.pos, tree.tpe) case Apply( Select(qual, nme.filter), @@ -580,7 +608,7 @@ abstract class RefChecks extends InfoTransform { case Ident(name) => if (sym.isSourceMethod && sym.hasFlag(CASE)) - result = toConstructor + result = toConstructor(tree.pos, tree.tpe) else if (name != nme.WILDCARD && name != nme.WILDCARD_STAR.toTypeName) { assert(sym != NoSymbol, tree)//debug enterReference(tree.pos, sym) @@ -588,7 +616,7 @@ abstract class RefChecks extends InfoTransform { case Select(qual, name) => if (sym.isSourceMethod && sym.hasFlag(CASE)) - result = toConstructor + result = toConstructor(tree.pos, tree.tpe) else qual match { case Super(qualifier, mix) => val base = qual.symbol; diff --git a/test/files/neg/bug877.check b/test/files/neg/bug877.check index 081d5066ae..77c4222839 100644 --- a/test/files/neg/bug877.check +++ b/test/files/neg/bug877.check @@ -1,4 +1,4 @@ bug877.scala:3: error: `{' expected -trait Foo extends A(22A, Bug!) {}
+trait Foo extends A(22A, Bug!) {} ^ one error found |