summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-01-10 19:24:14 +0000
committerMartin Odersky <odersky@gmail.com>2007-01-10 19:24:14 +0000
commitd1d980fd2b51304c504bff2529378a31b1ad91e9 (patch)
treecbe3e64fe35e157625c46fde06a3873a7aa50135 /src
parent181cefa87219f65d9b6d101049d4916db6715092 (diff)
downloadscala-d1d980fd2b51304c504bff2529378a31b1ad91e9.tar.gz
scala-d1d980fd2b51304c504bff2529378a31b1ad91e9.tar.bz2
scala-d1d980fd2b51304c504bff2529378a31b1ad91e9.zip
fixed bug877
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala23
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala50
3 files changed, 54 insertions, 23 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;