From 76c06b4661b70e934530a0debad34a5766ee43e9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 17 Jan 2008 16:37:27 +0000 Subject: build target is now 1.5 case classes now generate objects not factory methods. some small cleanups for type inference --- build.xml | 26 +- lib/scala-compiler.jar.desired.sha1 | 2 +- lib/scala-library.jar.desired.sha1 | 2 +- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 21 +- src/compiler/scala/tools/nsc/ast/TreeInfo.scala | 16 - src/compiler/scala/tools/nsc/ast/Trees.scala | 2 + .../nsc/backend/opt/DeadCodeElimination.scala | 2 +- .../tools/nsc/matching/ParallelMatching.scala | 6 +- .../scala/tools/nsc/matching/PatternNodes.scala | 6 +- src/compiler/scala/tools/nsc/symtab/Flags.scala | 2 +- src/compiler/scala/tools/nsc/symtab/StdNames.scala | 1 + src/compiler/scala/tools/nsc/symtab/Symbols.scala | 16 +- src/compiler/scala/tools/nsc/symtab/Types.scala | 37 +- .../scala/tools/nsc/transform/Constructors.scala | 9 +- .../scala/tools/nsc/transform/Erasure.scala | 2 +- src/compiler/scala/tools/nsc/transform/Mixin.scala | 2 +- .../scala/tools/nsc/typechecker/Analyzer.scala | 2 +- .../scala/tools/nsc/typechecker/Contexts.scala | 2 +- .../scala/tools/nsc/typechecker/Infer.scala | 111 ++++-- .../scala/tools/nsc/typechecker/Namers.scala | 125 ++++--- .../scala/tools/nsc/typechecker/RefChecks.scala | 31 +- .../scala/tools/nsc/typechecker/Typers.scala | 109 +++--- .../scala/tools/nsc/typechecker/Unapplies.scala | 88 ++++- src/library/scala/collection/jcl/SortedSet.scala | 4 +- test/files/jvm/serialization.check | 146 ++++++++ test/files/jvm/serialization.scala | 345 +++++++++++++++++++ test/files/jvm/typerep.check | 47 +++ test/files/jvm/typerep.scala | 374 +++++++++++++++++++++ test/files/neg/bug414.check | 4 +- test/files/neg/bug692.check | 2 +- test/files/neg/bug692.scala | 2 +- test/files/neg/bug783.check | 6 +- test/files/neg/bug960.check | 5 +- test/files/neg/bug961.scala | 2 +- test/files/neg/scopes.check | 7 +- test/files/pos/bug432.scala | 2 + test/files/run/bug874.scala | 22 -- test/files/run/caseclasses.check | 2 + test/files/run/caseclasses.scala | 15 + test/files/run/classof.check | 1 + test/files/run/classof.scala | 8 + test/pending/run/bug874.scala | 17 + test/pending/run/classof.check | 1 - test/pending/run/classof.scala | 8 - 44 files changed, 1395 insertions(+), 245 deletions(-) create mode 100755 test/files/jvm/serialization.check create mode 100755 test/files/jvm/serialization.scala create mode 100755 test/files/jvm/typerep.check create mode 100755 test/files/jvm/typerep.scala create mode 100644 test/files/pos/bug432.scala delete mode 100644 test/files/run/bug874.scala create mode 100644 test/files/run/classof.check create mode 100755 test/files/run/classof.scala create mode 100755 test/pending/run/bug874.scala delete mode 100644 test/pending/run/classof.check delete mode 100644 test/pending/run/classof.scala diff --git a/build.xml b/build.xml index 1043c8f97a..125cf87864 100644 --- a/build.xml +++ b/build.xml @@ -493,7 +493,7 @@ BUILD QUICK-TEST LAYER srcdir="${src.dir}/library" destdir="${quick.dir}/lib/library" usepredefs="no" - addparams="${nsc.params}" target="jvm-1.4" + addparams="${nsc.params}" target="jvm-1.5" deprecation="yes" unchecked="yes" scalacdebugging="${nsc.log-files}" classpath="${quick.dir}/lib/library" @@ -501,7 +501,7 @@ BUILD QUICK-TEST LAYER @@ -526,7 +526,7 @@ BUILD QUICK-TEST LAYER @@ -547,7 +547,7 @@ BUILD QUICK-TEST LAYER @@ -562,7 +562,7 @@ BUILD QUICK-TEST LAYER @@ -591,7 +591,7 @@ BUILD QUICK-TEST LAYER @@ -1207,14 +1207,14 @@ TEST srcdir="${src.dir}/library" destdir="${strap.dir}/lib/library" usepredefs="no" - addparams="${nsc.params}" target="jvm-1.4" + addparams="${nsc.params}" target="jvm-1.5" deprecation="yes" unchecked="yes" classpath="${strap.dir}/lib/library" includes="scala/Predef.scala"/> @@ -1238,7 +1238,7 @@ TEST @@ -1258,7 +1258,7 @@ TEST + addparams="${nsc.params}" target="jvm-1.5"> @@ -1271,7 +1271,7 @@ TEST + addparams="${nsc.params}" target="jvm-1.5"> @@ -1298,7 +1298,7 @@ TEST @@ -1463,7 +1463,7 @@ DOCUMENTATION diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1 index 20b6d0396f..c25fab0e6c 100644 --- a/lib/scala-compiler.jar.desired.sha1 +++ b/lib/scala-compiler.jar.desired.sha1 @@ -1 +1 @@ -89ceb76a10d98baef63a75a90038c0a15b84bcc3 ?scala-compiler.jar +abff2e45f1331c5e794712eb3b541d91977833c1 ?scala-compiler.jar diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1 index ffa7465d0f..9724c9631e 100644 --- a/lib/scala-library.jar.desired.sha1 +++ b/lib/scala-library.jar.desired.sha1 @@ -1 +1 @@ -93774afad0ec5a940628a89348e097050bb25467 ?scala-library.jar +bb122f3e11a64e6c5b60e849cdda1db4129cb3f2 ?scala-library.jar diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 1aaa2f41bf..f37a34ae74 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -18,6 +18,21 @@ abstract class TreeGen { import definitions._ import posAssigner.atPos + def scalaDot(name: Name): Tree = + Select(Ident(nme.scala_) setSymbol ScalaPackage, name) + def scalaAnyRefConstr: Tree = + scalaDot(nme.AnyRef.toTypeName) + def scalaUnitConstr: Tree = + scalaDot(nme.Unit.toTypeName) + def scalaScalaObjectConstr: Tree = + scalaDot(nme.ScalaObject.toTypeName) + def productConstr: Tree = + scalaDot(nme.Product.toTypeName) + + def scalaFunctionConstr(argtpes: List[Tree], restpe: Tree): Tree = + AppliedTypeTree( + scalaDot(newTypeName("Function"+argtpes.length)), + argtpes ::: List(restpe)) /** Builds a reference to value whose type is given stable prefix. * The type must be suitable for this. For example, it @@ -135,7 +150,6 @@ abstract class TreeGen { This(sym.name) setSymbol sym setType sym.thisType def mkAttributedIdent(sym: Symbol): Tree = { - assert(sym.isTerm, sym) Ident(sym.name) setSymbol sym setType sym.tpe } @@ -145,7 +159,6 @@ abstract class TreeGen { qual.symbol.name.toTermName == nme.EMPTY_PACKAGE_NAME)) { mkAttributedIdent(sym) } else { - assert(sym.isTerm) val result = Select(qual, sym.name) setSymbol sym if (qual.tpe ne null) result setType qual.tpe.memberType(sym) result @@ -207,7 +220,9 @@ abstract class TreeGen { /** Builds a tuple */ def mkTuple(elems: List[Tree]): Tree = if (elems.isEmpty) Literal(()) - else Apply(mkAttributedRef(definitions.TupleClass(elems.length).caseFactory), elems) + else Apply( + Select(mkAttributedRef(definitions.TupleClass(elems.length).caseModule), nme.apply), + elems) def mkAnd(tree1: Tree, tree2: Tree) = Apply(Select(tree1, Boolean_and), List(tree2)) diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index d814c5cd6c..b6dd026a84 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -244,22 +244,6 @@ abstract class TreeInfo { case _ => false } - /** is this pattern of the form S(...) where S is a subclass of Seq - * and S is not a case class? The pattern might be wrapped in binds or alternatives. - */ - def isSequencePattern(tree: Tree): Boolean = tree match { - case Apply(fn, _) => - (fn.symbol ne null) && - !fn.symbol.hasFlag(CASE) && - fn.symbol.isNonBottomSubClass(definitions.SeqClass) - case Bind(name, body) => - isSequencePattern(body) - case Alternative(ts) => - ts forall isSequencePattern - case _ => - false - } - /** The method part of an application node */ def methPart(tree: Tree): Tree = tree match { diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 4412aa0896..81f10c7a31 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -755,6 +755,8 @@ trait Trees { case class TypeTree() extends TypTree { var original: Tree = _ + override def symbol = tpe.typeSymbol + def setOriginal(tree: Tree): this.type = { original = tree setPos(tree.pos) diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala index 4fb9f310b1..b7355c86ff 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala @@ -244,7 +244,7 @@ abstract class DeadCodeElimination extends SubComponent { def find(bb: BasicBlock): Option[(BasicBlock, Int)] = { var xs = bb.toList xs.zipWithIndex find { hd => hd._1 eq i } match { - case Some(_, idx) => Some(bb, idx) + case Some((_, idx)) => Some(bb, idx) case None => None } } diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index d019b4cc89..6814ef7465 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -673,9 +673,9 @@ trait ParallelMatching { pat match { case Bind(_,p) => subpatterns(p) - case app @ Apply(fn, pats) if isCaseClass(app.tpe) && (fn.symbol eq null)=> + case app @ Apply(fn, pats) if isCaseClass(app.tpe) && fn.isType => if (isCaseHead) pats else dummies - case Apply(fn,xs) => assert((xs.isEmpty) && (fn.symbol ne null), "strange Apply"); dummies // named constant + case Apply(fn,xs) => assert((xs.isEmpty) && (!fn.isType), "strange Apply"); dummies // named constant case _: UnApply => dummies case pat => @@ -1230,7 +1230,7 @@ trait ParallelMatching { */ final def applyRule(implicit theOwner: Symbol, rep: RepFactory): RuleApplication = row match { case Nil => - ErrorRule + ErrorRule() case Row(pats, subst, g, bx)::xs => var px = 0; var rpats = pats; var bnd = subst; var temps = temp; while((bnd ne null) && (rpats ne Nil)) { val (vs,p) = strip(rpats.head); diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala index 92b59ff20f..030e46175f 100644 --- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala +++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala @@ -78,14 +78,14 @@ trait PatternNodes { self: transform.ExplicitOuter => } object Apply_Value { - def unapply(x:Apply) = if ((x.symbol ne null) && (x.args eq Nil)) Some(x.tpe.prefix, x.symbol) else None + def unapply(x:Apply) = if (!x.fun.isType && x.args.isEmpty) Some(x.tpe.prefix, x.symbol) else None } object Apply_CaseClass_NoArgs { - def unapply(x:Apply) = if ((x.symbol eq null) && (x.args eq Nil)) Some(x.tpe) else None + def unapply(x:Apply) = if (x.fun.isType && x.args.isEmpty) Some(x.tpe) else None } object Apply_CaseClass_WithArgs { - def unapply(x:Apply) = if (x.symbol eq null) true else false + def unapply(x:Apply) = x.fun.isType } object __UnApply { diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala index eefc6457e4..7befdc9719 100644 --- a/src/compiler/scala/tools/nsc/symtab/Flags.scala +++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala @@ -126,7 +126,7 @@ object Flags extends Enumeration { final val PickledFlags: Long = 0xFFFFFFFFL /** Module flags inherited by their module-class */ - final val ModuleToClassFlags: Long = AccessFlags | PACKAGE | CASE + final val ModuleToClassFlags: Long = AccessFlags | MODULE | PACKAGE | CASE | SYNTHETIC private def listToString(ss: List[String]): String = ss.filter("" !=).mkString("", " ", "") diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index 68e5e35f60..f6a2904a45 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -215,6 +215,7 @@ trait StdNames { val Finally = newTermName("Finally") val Float = newTermName("Float") val Function = newTermName("Function") + val Function1 = newTermName("Function1") val Int = newTermName("Int") val Labelled = newTermName("Labelled") val Long = newTermName("Long") diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 5bec708d45..e085c13e9c 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -261,9 +261,9 @@ trait Symbols { final def isPrimaryConstructor = isConstructor && owner.primaryConstructor == this - /** Is this symbol a case class factory method? */ - final def isCaseFactory = - isMethod && hasFlag(CASE) + /** Is this symbol a synthetic apply or unapply method in a companion object of a case class? */ + final def isCaseApplyOrUnapply = + isMethod && hasFlag(CASE) && hasFlag(SYNTHETIC) /** Is this symbol an implementation class for a mixin? */ final def isImplClass: Boolean = isClass && hasFlag(IMPLCLASS) @@ -930,14 +930,14 @@ trait Symbols { 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 + /** The case module corresponding to this case class * @pre case class is a member of some other class or package */ - final def caseFactory: Symbol = { - var facname = name.toTermName + final def caseModule: Symbol = { + var modname = name.toTermName if (privateWithin.isClass && !privateWithin.isModuleClass && !hasFlag(EXPANDEDNAME)) - facname = privateWithin.expandedName(facname) - initialize.owner.info.decl(facname).suchThat(_.isCaseFactory) + modname = privateWithin.expandedName(modname) + initialize.owner.info.decl(modname).suchThat(_.isModule) } /** If this symbol is a type parameter skolem (not an existential skolem!) diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index f690766561..1f24ff1bf6 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -139,6 +139,7 @@ trait Types { override def termSymbol = underlying.termSymbol override def termSymbolDirect = underlying.termSymbolDirect override def typeParams = underlying.typeParams + override def boundSyms = underlying.boundSyms override def typeSymbol = underlying.typeSymbol override def typeSymbolDirect = underlying.typeSymbolDirect override def widen = underlying.widen @@ -172,7 +173,6 @@ trait Types { override def paramSectionCount = 0 override def paramTypes: List[Type] = List() override def typeArgs = underlying.typeArgs - override def typeParams = underlying.typeParams override def notNull = maybeRewrap(underlying.notNull) override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = underlying.instantiateTypeParams(formals, actuals) override def skolemizeExistential(owner: Symbol, origin: AnyRef) = underlying.skolemizeExistential(owner, origin) @@ -296,10 +296,14 @@ trait Types { * the empty list for all other types */ def paramTypes: List[Type] = List() - /** For a poly type, its type parameters, + /** For a (potentially wrapped) poly type, its type parameters, * the empty list for all other types */ def typeParams: List[Symbol] = List() + /** For a (potentially wrapped) poly or existential type, its bound symbols, + * the empty list for all other types */ + def boundSyms: List[Symbol] = List() + /** Mixin a NotNull trait unless type already has one */ def notNull: Type = if (isNotNull || phase.erasedTypes) this else NotNullType(this) @@ -709,8 +713,8 @@ trait Types { var skolems: List[Symbol] = List() for (t <- this) { t match { - case ExistentialType(tparams, qtpe) => - boundSyms = boundSyms ::: tparams + case ExistentialType(quantified, qtpe) => + boundSyms = boundSyms ::: quantified case TypeRef(_, sym, _) => if ((sym hasFlag EXISTENTIAL) && !(boundSyms contains sym) && !(skolems contains sym)) skolems = sym :: skolems @@ -1610,6 +1614,7 @@ A type's typeSymbol should never be inspected directly. override def decls: Scope = resultType.decls override def termSymbol: Symbol = resultType.termSymbol override def typeSymbol: Symbol = resultType.typeSymbol + override def boundSyms: List[Symbol] = typeParams override def prefix: Type = resultType.prefix override def closure: Array[Type] = resultType.closure override def closureDepth: Int = resultType.closureDepth @@ -1654,6 +1659,7 @@ A type's typeSymbol should never be inspected directly. override def isStable: Boolean = false override def bounds = TypeBounds(maybeRewrap(underlying.bounds.lo), maybeRewrap(underlying.bounds.hi)) override def parents = underlying.parents map maybeRewrap + override def boundSyms: List[Symbol] = quantified override def prefix = maybeRewrap(underlying.prefix) override def typeArgs = underlying.typeArgs map maybeRewrap override def paramTypes = underlying.paramTypes map maybeRewrap @@ -2648,8 +2654,22 @@ A type's typeSymbol should never be inspected directly. else if (matches(from.head, sym)) toType(tp, to.head) else subst(tp, sym, from.tail, to.tail) + private def renameBoundSyms(tp: Type) = tp match { + case PolyType(bs, restp) => + val bs1 = cloneSymbols(bs) + PolyType(bs1, restp.substSym(bs, bs1)) + case ExistentialType(bs, restp) => + val bs1 = cloneSymbols(bs) + ExistentialType(bs1, restp.substSym(bs, bs1)) + case _ => + tp + } + def apply(tp0: Type): Type = if (from.isEmpty) tp0 else { - val tp = mapOver(tp0) + val boundSyms = tp0.boundSyms + val tp1 = if (boundSyms.isEmpty || !(boundSyms exists (from contains))) tp0 + else renameBoundSyms(tp0) + val tp = mapOver(tp1) tp match { // @M @@ -2673,13 +2693,6 @@ A type's typeSymbol should never be inspected directly. } case SingleType(NoPrefix, sym) => subst(tp, sym, from, to) - case PolyType(tparams, restp) => - assert(!(tparams exists (from contains))) - tp - case ExistentialType(tparams, restp) => - if (tparams exists (from contains)) - assert(false, "["+from.mkString(",")+":="+to.mkString(",")+"]"+tp) - tp case _ => tp } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index b03c05ce3b..d7150d981f 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -154,12 +154,18 @@ abstract class Constructors extends Transform { if (stat.symbol.tpe.isInstanceOf[ConstantType]) assert(stat.symbol.getter(stat.symbol.owner) != NoSymbol, stat) else { + try { if (rhs != EmptyTree && !stat.symbol.hasFlag(LAZY)) { val rhs1 = intoConstructor(stat.symbol, rhs); (if (canBeMoved(stat)) constrPrefixBuf else constrStatBuf) += mkAssign( stat.symbol, rhs1) } defBuf += copy.ValDef(stat, mods, name, tpt, EmptyTree) + } catch { + case ex: Throwable => + println("error when transforming "+stat+" in "+stats) + throw ex + } } case ClassDef(_, _, _, _) => defBuf += (new ConstructorTransformer).transform(stat) @@ -205,14 +211,13 @@ abstract class Constructors extends Transform { defBuf.toList filter (stat => isAccessed(stat.symbol))) } - override def transform(tree: Tree): Tree = { + override def transform(tree: Tree): Tree = tree match { case ClassDef(mods, name, tparams, impl) if !tree.symbol.hasFlag(INTERFACE) => copy.ClassDef(tree, mods, name, tparams, transformClassTemplate(impl)) case _ => super.transform(tree) } - } } // ConstructorTransformer diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 80a1fc1f0c..a83c68f797 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -763,7 +763,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { */ private val preTransformer = new Transformer { override def transform(tree: Tree): Tree = { - if (tree.symbol == ArrayClass) return tree + if (tree.symbol == ArrayClass && !tree.isType) return tree val tree1 = tree match { case ClassDef(mods, name, tparams, impl) => if (settings.debug.value) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 8bf0994af6..144081efcb 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -59,7 +59,7 @@ abstract class Mixin extends InfoTransform { * inherits the trait. */ private def isForwarded(sym: Symbol) = - isImplementedStatically(sym) && !sym.isImplOnly && !sym.isCaseFactory + isImplementedStatically(sym) && !sym.isImplOnly /** Maps the type of an implementation class to its interface; * maps all other types to themselves. diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala index defcc6ce2e..4ede3dec3b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala @@ -35,7 +35,7 @@ trait Analyzer extends AnyRef val global: Analyzer.this.global.type = Analyzer.this.global val phaseName = "typer" def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) { - resetTyper + resetTyper() def apply(unit: CompilationUnit) { unit.body = newTyper(rootContext(unit)).typed(unit.body) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index f0311dd885..782c003b25 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -76,7 +76,7 @@ trait Contexts { self: Analyzer => c } - def resetContexts { + def resetContexts() { var sc = startContext while (sc != NoContext) { sc.tree match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 8571148479..ea2a4c59c8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -512,12 +512,33 @@ trait Infer { if (targ.typeSymbol == AllClass && (varianceInType(restpe)(tparam) & COVARIANT) == 0) { uninstantiated += tparam tparam.tpe //@M TODO: might be affected by change to tpe in Symbol - } else targ.widen + } else if (targ.typeSymbol == RepeatedParamClass) { + targ.baseType(SeqClass) + } else { + targ.widen + } } // println("meth type args "+", tparams = "+tparams+", formals = "+formals+", restpe = "+restpe+", argtpes = "+argtpes+", underlying = "+(argtpes map (_.widen))+", pt = "+pt+", uninstantiated = "+uninstantiated.toList+", result = "+res) //DEBUG // res } + def followApply(tp: Type): Type = tp match { + case PolyType(List(), restp) => + val restp1 = followApply(restp) + if (restp1 eq restp) tp else restp1 + case _ => + val appmeth = tp.nonPrivateMember(nme.apply) filter (_.isPublic) + if (appmeth == NoSymbol) tp + else OverloadedType(tp, appmeth.alternatives) + } + + def hasExactlyNumParams(tp: Type, n: Int): Boolean = tp match { + case OverloadedType(pre, alts) => + alts exists (alt => hasExactlyNumParams(pre.memberType(alt), n)) + case _ => + formalTypes(tp.paramTypes, n).length == n + } + /** Is there an instantiation of free type variables undetparams * such that function type ftpe is applicable to * argtpes and its result conform to pt? @@ -531,6 +552,8 @@ trait Infer { def isApplicable(undetparams: List[Symbol], ftpe: Type, argtpes0: List[Type], pt: Type): Boolean = ftpe match { + case OverloadedType(pre, alts) => + alts exists (alt => isApplicable(undetparams, pre.memberType(alt), argtpes0, pt)) case ExistentialType(tparams, qtpe) => isApplicable(undetparams, qtpe, argtpes0, pt) case MethodType(formals0, _) => @@ -573,29 +596,70 @@ trait Infer { } } - /** Does type ftpe1 specialize type ftpe2 + /** Is type ftpe1 strictly more specific than type ftpe2 * when both are alternatives in an overloaded function? + * @see SLS (sec:overloading-resolution) * * @param ftpe1 ... * @param ftpe2 ... * @return ... */ - def specializes(ftpe1: Type, ftpe2: Type): Boolean = ftpe1 match { + def isMoreSpecific(ftpe1: Type, ftpe2: Type): Boolean = ftpe1 match { + case OverloadedType(pre, alts) => + alts exists (alt => isMoreSpecific(pre.memberType(alt), ftpe2)) case et: ExistentialType => - et.withTypeVars(specializes(_, ftpe2)) - case MethodType(formals, _) => + et.withTypeVars(isStrictlyMoreSpecific(_, ftpe2)) + case MethodType(formals @ (x :: xs), _) => isApplicable(List(), ftpe2, formals, WildcardType) - case PolyType(tparams, MethodType(formals, _)) => + case PolyType(_, MethodType(formals @ (x :: xs), _)) => isApplicable(List(), ftpe2, formals, WildcardType) case ErrorType => true case _ => - false + ftpe2 match { + case OverloadedType(pre, alts) => + alts forall (alt => isMoreSpecific(ftpe1, pre.memberType(alt))) + case et: ExistentialType => + et.withTypeVars(isStrictlyMoreSpecific(ftpe1, _)) + case MethodType(_, _) | PolyType(_, MethodType(_, _)) => + true + case _ => + isMoreSpecificValueType(ftpe1, ftpe2, List(), List()) + } } + def isStrictlyMoreSpecific(ftpe1: Type, ftpe2: Type): Boolean = + ftpe1.isError || isMoreSpecific(ftpe1, ftpe2) && + (!isMoreSpecific(ftpe2, ftpe1) || + !ftpe1.isInstanceOf[OverloadedType] && ftpe2.isInstanceOf[OverloadedType]) + + def isMoreSpecificValueType(tpe1: Type, tpe2: Type, undef1: List[Symbol], undef2: List[Symbol]): Boolean = (tpe1, tpe2) match { + case (PolyType(tparams1, rtpe1), _) => + isMoreSpecificValueType(rtpe1, tpe2, undef1 ::: tparams1, undef2) + case (_, PolyType(tparams2, rtpe2)) => + isMoreSpecificValueType(tpe1, rtpe2, undef1, undef2 ::: tparams2) + case _ => + existentialAbstraction(undef1, tpe1) <:< existentialAbstraction(undef2, tpe2) + } + +/* /** Is type `tpe1' a strictly better expression alternative than type `tpe2'? */ def isStrictlyBetterExpr(tpe1: Type, tpe2: Type) = { + isMethod(tpe2) && !isMethod(tpe1) || + isNullary(tpe1) && !isNullary(tpe2) || + isStrictlyBetter(tpe1, tpe2) + } + + /** Is type `tpe1' a strictly better alternative than type `tpe2'? + * non-methods are always strictly better than methods + * nullary methods are always strictly better than non-nullary + * if both are non-nullary methods, then tpe1 is strictly better than tpe2 if + * - tpe1 specializes tpe2 and tpe2 does not specialize tpe1 + * - tpe1 and tpe2 specialize each other and tpe1 has a strictly better resulttype than + * tpe2 + */ + def isStrictlyBetter(tpe1: Type, tpe2: Type) = { def isNullary(tpe: Type): Boolean = tpe match { case tp: RewrappingTypeProxy => isNullary(tp.underlying) case _ => tpe.paramSectionCount == 0 || tpe.paramTypes.isEmpty @@ -605,16 +669,21 @@ trait Infer { case MethodType(_, _) | PolyType(_, _) => true case _ => false } - isMethod(tpe2) && !isMethod(tpe1) || + def hasStrictlyBetterResult = + resultIsBetter(tpe1, tpe2, List(), List()) && !resultIsBetter(tpe2, tpe1, List(), List()) + if (!isMethod(tpe1)) + isMethod(tpe2) || hasStrictlyBetterResult + isNullary(tpe1) && !isNullary(tpe2) || - isStrictlyBetter(tpe1, tpe2) - } + is - /** Is type `tpe1' a strictly better alternative than type `tpe2'? - */ - def isStrictlyBetter(tpe1: Type, tpe2: Type) = - specializes(tpe1, tpe2) && !specializes(tpe2, tpe1) + else if (isNullary(tpe1)) + isMethod(tpe2) && (!isNullary(tpe2) || hasStrictlyBetterResult) + else + specializes(tpe1, tpe2) && (!specializes(tpe2, tpe1) || hasStrictlyBetterResult) + } +*/ /** error if arguments not within bounds. */ def checkBounds(pos: Position, pre: Type, owner: Symbol, tparams: List[Symbol], targs: List[Type], prefix: String) = { @@ -715,7 +784,7 @@ trait Infer { else if (s.isContravariant) "contravariant" else "invariant"; - def qualify(a0: Symbol, b0: Symbol): String = if(a0.toString != b0.toString) "" else { + def qualify(a0: Symbol, b0: Symbol): String = if (a0.toString != b0.toString) "" else { assert((a0 ne b0) && (a0.owner ne b0.owner)); var a = a0; var b = b0 while (a.owner.name == b.owner.name) { a = a.owner; b = b.owner} @@ -1123,7 +1192,7 @@ trait Infer { */ def inferExprAlternative(tree: Tree, pt: Type): Unit = tree.tpe match { case OverloadedType(pre, alts) => tryTwice { - var alts1 = alts filter (alt => isCompatible(pre.memberType(alt), pt)) + var alts1 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt)) var secondTry = false if (alts1.isEmpty) { alts1 = alts @@ -1134,8 +1203,8 @@ trait Infer { { val tp1 = pre.memberType(sym1) val tp2 = pre.memberType(sym2) (tp2 == ErrorType || - !global.typer.infer.isCompatible(tp2, pt) && global.typer.infer.isCompatible(tp1, pt) || - isStrictlyBetterExpr(tp1, tp2)) } + !global.typer.infer.isWeaklyCompatible(tp2, pt) && global.typer.infer.isWeaklyCompatible(tp1, pt) || + isStrictlyMoreSpecific(tp1, tp2)) } val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) => if (improves(alt, best)) alt else best) val competing = alts1 dropWhile (alt => best == alt || improves(best, alt)) @@ -1161,7 +1230,7 @@ trait Infer { } } else { val applicable = alts1 filter (alt => - global.typer.infer.isCompatible(pre.memberType(alt), pt)) + global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt)) checkNotShadowed(tree.pos, pre, best, applicable) tree.setSymbol(best).setType(pre.memberType(best)) } @@ -1180,10 +1249,10 @@ trait Infer { case OverloadedType(pre, alts) => tryTwice { if (settings.debug.value) log("infer method alt " + tree.symbol + " with alternatives " + (alts map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt) - val applicable = alts filter (alt => isApplicable(undetparams, pre.memberType(alt), argtpes, pt)) + val applicable = alts filter (alt => isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) def improves(sym1: Symbol, sym2: Symbol) = sym2 == NoSymbol || sym2.isError || - isStrictlyBetter(pre.memberType(sym1), pre.memberType(sym2)) + isStrictlyMoreSpecific(followApply(pre.memberType(sym1)), followApply(pre.memberType(sym2))) val best = ((NoSymbol: Symbol) /: applicable) ((best, alt) => if (improves(alt, best)) alt else best) val competing = applicable dropWhile (alt => best == alt || improves(best, alt)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index e236f0f7e7..4f6d1682ad 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -6,6 +6,7 @@ package scala.tools.nsc.typechecker +import scala.collection.mutable.HashMap import scala.tools.nsc.util.Position import symtab.Flags import symtab.Flags._ @@ -18,6 +19,7 @@ import symtab.Flags._ trait Namers { self: Analyzer => import global._ import definitions._ + import posAssigner.atPos /** Convert to corresponding type parameters all skolems which satisfy one * of the following two conditions: @@ -41,6 +43,12 @@ trait Namers { self: Analyzer => private class NormalNamer(context : Context) extends Namer(context) def newNamer(context : Context) : Namer = new NormalNamer(context) + private val caseClassOfModuleClass = new HashMap[Symbol, ClassDef] + + def resetNamer() { + caseClassOfModuleClass.clear + } + abstract class Namer(val context: Context) { val typer = newTyper(context) @@ -51,6 +59,14 @@ trait Namers { self: Analyzer => sym } + + def inConstructorFlag: Long = + if (context.owner.isConstructor && !context.inConstructorSuffix || context.owner.isEarly) INCONSTRUCTOR + else 0l + + def moduleClassFlags(moduleFlags: Long) = + (moduleFlags & ModuleToClassFlags) | FINAL | inConstructorFlag + def updatePosFlags(sym: Symbol, pos: Position, flags: Long): Symbol = { if (settings.debug.value) log("overwriting " + sym) val lockedFlag = sym.flags & LOCKED @@ -58,7 +74,7 @@ trait Namers { self: Analyzer => sym setPos pos sym.flags = flags | lockedFlag if (sym.isModule && sym.moduleClass != NoSymbol) - updatePosFlags(sym.moduleClass, pos, (flags & ModuleToClassFlags) | MODULE | FINAL) + updatePosFlags(sym.moduleClass, pos, moduleClassFlags(flags)) if (sym.owner.isPackageClass && (sym.linkedSym.rawInfo.isInstanceOf[loaders.SymbolLoader] || sym.linkedSym.rawInfo.isComplete && runId(sym.validTo) != currentRunId)) @@ -112,13 +128,20 @@ trait Namers { self: Analyzer => !((newS.owner.isTypeParameter || newS.owner.isAbstractType) && newS.name.length==1 && newS.name(0)=='_') //@M: allow repeated use of `_' for higher-order type params } + + // IDE hook protected def setInfo[Sym <: Symbol](sym : Sym)(tpe : LazyType) : Sym = sym.setInfo(tpe) + private def doubleDefError(pos: Position, sym: Symbol) { context.error(pos, sym.name.toString() + " is already defined as " + (if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString())) } + private def inCurrentScope(m: Symbol) = + if (context.owner.isClass) context.owner == m.owner + else context.scope == m.owner.info.decls + def enterInScope(sym: Symbol): Symbol = { // allow for overloaded methods if (!(sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass)) { @@ -149,10 +172,6 @@ trait Namers { self: Analyzer => } } - def inConstructorFlag: Long = - if (context.owner.isConstructor && !context.inConstructorSuffix || context.owner.isEarly) INCONSTRUCTOR - else 0l - def enterClassSymbol(tree : ClassDef): Symbol = { var c: Symbol = context.scope.lookup(tree.name); if (!inIDE && c.isType && context.scope == c.owner.info.decls && !currentRun.compiles(c)) { @@ -179,21 +198,25 @@ trait Namers { self: Analyzer => assert(c.name.toString.indexOf('(') == -1) c } + + /** Enter a module symbol. The tree parameter can be either a module definition + * or a class definition */ def enterModuleSymbol(tree : ModuleDef): Symbol = { // .pos, mods.flags | MODULE | FINAL, name - assert(tree.name.isTermName) var m: Symbol = context.scope.lookup(tree.name) - if (!inIDE && m.isModule && !m.isPackage && (context.scope == m.owner.info.decls) && - !currentRun.compiles(m)) { - updatePosFlags(m, tree.pos, tree.mods.flags|MODULE|FINAL) + val moduleFlags = tree.mods.flags | MODULE | FINAL + if (!inIDE && m.isModule && !m.isPackage && inCurrentScope(m) && + (!currentRun.compiles(m) || (m hasFlag SYNTHETIC))) { + updatePosFlags(m, tree.pos, moduleFlags) setPrivateWithin(tree, m, tree.mods) + synthetics -= m } else { m = context.owner.newModule(tree.pos, tree.name) - m.setFlag(tree.mods.flags) + m.setFlag(moduleFlags) m = setPrivateWithin(tree, m, tree.mods) m = enterInScope(m) - m.moduleClass.setFlag(tree.mods.flags|MODULE|FINAL| inConstructorFlag) + m.moduleClass.setFlag(moduleClassFlags(moduleFlags)) setPrivateWithin(tree, m.moduleClass, tree.mods) } if (m.owner.isPackageClass) { @@ -203,26 +226,6 @@ trait Namers { self: Analyzer => m } - def enterCaseFactorySymbol(tree : ClassDef): Symbol = { - val pos = tree.pos - val flags = tree.mods.flags & AccessFlags | METHOD | CASE - val name = tree.name.toTermName - var m: Symbol = context.scope.lookup(name) - if (!inIDE && m.isTerm && !m.isPackage && !currentRun.compiles(m) && context.scope == m.owner.info.decls) { - updatePosFlags(m, pos, flags) - setPrivateWithin(tree, m, tree.mods) - } else { - // recycle the old fashion way. - m = enterInScope{ - var sym = context.owner.newMethod(pos, name).setFlag(flags) - sym = setPrivateWithin(tree, sym, tree.mods) - sym - } - } - if (m.owner.isPackageClass) - currentRun.symSource(m) = context.unit.source.file - m - } def enterSyms(trees: List[Tree]): Namer = { var namer : Namer = this for (tree <- trees) { @@ -231,6 +234,7 @@ trait Namers { self: Analyzer => } namer } + def newTypeSkolems(tparams: List[Symbol]): List[Symbol] = { val tskolems = tparams map (_.newTypeSkolem) val ltp = new LazyType { @@ -280,7 +284,6 @@ trait Namers { self: Analyzer => } def finish = finishWith(List()) - if (tree.symbol == NoSymbol) { val owner = context.owner tree match { @@ -292,9 +295,12 @@ trait Namers { self: Analyzer => case tree @ ClassDef(mods, name, tparams, impl) => tree.symbol = enterClassSymbol(tree) finishWith(tparams) - if ((mods.flags & CASE) != 0) { // enter case factory method. - val sym = enterCaseFactorySymbol(tree) - setInfo(sym)(namerOf(sym).caseFactoryCompleter(reuse(tree))) + if ((mods.flags & CASE) != 0) { + var m: Symbol = context.scope.lookup(tree.name.toTermName).filter(! _.isSourceMethod) + if (!(m.isModule && inCurrentScope(m) && currentRun.compiles(m))) { + m = enterSyntheticSym(caseModuleDef(tree)) + } + caseClassOfModuleClass(m.moduleClass) = tree } case tree @ ModuleDef(mods, name, _) => tree.symbol = enterModuleSymbol(tree) @@ -370,6 +376,12 @@ trait Namers { self: Analyzer => this.context } + def enterSyntheticSym(tree: Tree): Symbol = { + enterSym(tree) + synthetics(tree.symbol) = tree + tree.symbol + } + // --- Lazy Type Assignment -------------------------------------------------- def typeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => @@ -421,14 +433,6 @@ trait Namers { self: Analyzer => sym.setInfo(selftpe) } - def caseFactoryCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => - val clazz = tree.symbol - var tpe = clazz.primaryConstructor.tpe - val tparams = clazz.typeParams - if (!tparams.isEmpty) tpe = PolyType(tparams, tpe).cloneInfo(sym); - sym.setInfo(tpe) - } - private def widenIfNotFinal(sym: Symbol, tpe: Type, pt: Type): Type = { val getter = if (sym.isValue && sym.owner.isClass && (sym hasFlag PRIVATE)) @@ -508,7 +512,14 @@ trait Namers { self: Analyzer => val parents = typer.parentTypes(templ) map checkParent enterSelf(templ.self) val decls = newClassScope(clazz) - newNamer(context.make(templ, clazz, decls)).enterSyms(templ.body) + val templateNamer = newNamer(context.make(templ, clazz, decls)) + .enterSyms(templ.body) + caseClassOfModuleClass get clazz match { + case Some(cdef) => + addApplyUnapply(cdef, templateNamer) + caseClassOfModuleClass -= clazz + case None => + } ClassInfoType(parents, decls, clazz) } @@ -733,6 +744,28 @@ trait Namers { self: Analyzer => else polyType(tparamSyms, tp) } + /** Given a case class + * + * case class C[Ts] (ps: Us) + * + * Add the following methods to toScope: + * + * 1. if case class is not abstract, add + * + * def apply[Ts](ps: Us): C[Ts] = new C[Ts](ps) + * + * 2. add a method + * + * def unapply[Ts](x: C[Ts]) = + * + * where is the caseClassUnapplyReturnValue of class C (see UnApplies.scala) + */ + def addApplyUnapply(cdef: ClassDef, namer: Namer) { + if (!(cdef.symbol hasFlag ABSTRACT)) + namer.enterSyntheticSym(caseModuleApplyMeth(cdef)) + namer.enterSyntheticSym(caseModuleUnapplyMeth(cdef)) + } + def typeSig(tree: Tree): Type = { val sym: Symbol = tree.symbol tree match { @@ -758,7 +791,7 @@ trait Namers { self: Analyzer => val clazz = sym.moduleClass clazz.setInfo(newNamer(context.makeNewScope(tree, clazz)).templateSig(impl)) //clazz.typeOfThis = singleType(sym.owner.thisType, sym); - clazz.tpe; + clazz.tpe case DefDef(_, _, tparams, vparamss, tpt, rhs) => val result = @@ -884,7 +917,7 @@ trait Namers { self: Analyzer => checkNoConflict(PRIVATE, PROTECTED) checkNoConflict(PRIVATE, OVERRIDE) checkNoConflict(DEFERRED, FINAL) - checkNoConflict(ABSTRACT, CASE) +// checkNoConflict(ABSTRACT, CASE) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 5c7841651b..e098224e59 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -373,7 +373,7 @@ abstract class RefChecks extends InfoTransform { var state = CoVariance while (sym != clazz && state != AnyVariance) { //Console.println("flip: " + sym + " " + sym.isParameter());//DEBUG - if ((sym hasFlag PARAM) && !sym.owner.isConstructor && !sym.owner.isCaseFactory && + if ((sym hasFlag PARAM) && !sym.owner.isConstructor && !sym.owner.isCaseApplyOrUnapply && !(tvar.isTypeParameterOrSkolem && sym.isTypeParameterOrSkolem && tvar.owner == sym.owner)) state = -state; else if (!sym.owner.isClass || @@ -574,9 +574,6 @@ abstract class RefChecks extends InfoTransform { } } - 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) @@ -635,32 +632,6 @@ 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 - if (factory == NoSymbol) { - assert(clazz.owner.isTerm, clazz) - List(transform(tree)) - } else { - def mkArgument(vparam: Symbol) = { - val id = Ident(vparam) - if (vparam.tpe.typeSymbol == 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 val ValDef(_, _, _, rhs) = tree1 diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 7429c9ccf7..ff31a95c8a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -38,13 +38,16 @@ trait Typers { self: Analyzer => private val superDefs = new HashMap[Symbol, ListBuffer[Tree]] - def resetTyper { + val synthetics = new HashMap[Symbol, Tree] + + def resetTyper() { resetContexts + resetNamer() transformed.clear superDefs.clear + synthetics.clear } - object UnTyper extends Traverser { override def traverse(tree: Tree) = { if (tree != EmptyTree) tree.tpe = null @@ -708,27 +711,32 @@ trait Typers { self: Analyzer => case _ => TypeTree(tree.tpe) setOriginal(tree) } } else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) { // (5) - val constr = tree.symbol.filter(_.isCaseFactory) - val clazz = constr.tpe.finalResultType.typeSymbol - if ((constr != NoSymbol) && (clazz hasFlag CASE)) { - val prefix = tree.tpe.finalResultType.prefix - val tree1 = TypeTree(clazz.primaryConstructor.tpe.asSeenFrom(prefix, clazz.owner)) setOriginal tree - try { - inferConstructorInstance(tree1, clazz.typeParams, pt) - } catch { - case tpe : TypeError => throw tpe - case t : Exception => - logError("CONTEXT: " + (tree.pos).dbgString, t) - throw t - } - tree1 - } else { - val extractor = tree.symbol.filter(sym => unapplyMember(sym.tpe).exists) - if (extractor != NoSymbol) { - tree setSymbol extractor + val extractor = tree.symbol.filter(sym => unapplyMember(sym.tpe).exists) + if (extractor != NoSymbol) { + tree setSymbol extractor + val unapply = unapplyMember(extractor.tpe) + val clazz = if (unapply.tpe.paramTypes.length == 1) unapply.tpe.paramTypes.head.typeSymbol + else NoSymbol + if ((unapply hasFlag CASE) && (clazz hasFlag CASE)) { + if (!phase.erasedTypes) checkStable(tree) //todo: do we need to demand this? + // convert synthetic unapply of case class to case class constructor + val prefix = tree.tpe.prefix + val tree1 = TypeTree(clazz.primaryConstructor.tpe.asSeenFrom(prefix, clazz.owner)) + .setOriginal(tree) + try { + inferConstructorInstance(tree1, clazz.typeParams, pt) + } catch { + case tpe : TypeError => throw tpe + case t : Exception => + logError("CONTEXT: " + (tree.pos).dbgString, t) + throw t + } + tree1 } else { - errorTree(tree, tree.symbol + " is not a case class constructor, nor does it have an unapply/unapplySeq method") + tree } + } else { + errorTree(tree, tree.symbol + " is not a case class constructor, nor does it have an unapply/unapplySeq method") } } else if ((mode & (EXPRmode | FUNmode)) == (EXPRmode | FUNmode) && !tree.tpe.isInstanceOf[MethodType] && @@ -1440,7 +1448,14 @@ trait Typers { self: Analyzer => if (vparam.tpt.isEmpty) vparam.tpt.tpe = if (isFullyDefined(argpt)) argpt - else { error(vparam.pos, "missing parameter type"); ErrorType } + else { + error( + vparam.pos, + "missing parameter type"+ + (if (vparam.mods.hasFlag(SYNTHETIC)) " for expanded function "+fun + else "")) + ErrorType + } enterSym(context, vparam) if (context.retyping) context.scope enter vparam.symbol vparam.symbol @@ -1479,7 +1494,9 @@ trait Typers { self: Analyzer => def typedImport(imp : Import) : Import = imp; def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { + val inBlock = exprOwner == context.owner + def typedStat(stat: Tree): Tree = { if (context.owner.isRefinementClass && !treeInfo.isDeclaration(stat)) errorTree(stat, "only declarations allowed here") @@ -1510,14 +1527,19 @@ trait Typers { self: Analyzer => result } } + def accesses(accessor: Symbol, accessed: Symbol) = (accessed hasFlag LOCAL) && (accessed hasFlag PARAMACCESSOR) || (accessor hasFlag ACCESSOR) && !(accessed hasFlag ACCESSOR) && accessed.isPrivateLocal - def checkNoDoubleDefs(stats: List[Tree]) { + + def checkNoDoubleDefsAndAddSynthetics(stats: List[Tree]): List[Tree] = { val scope = if (inBlock) context.scope else context.owner.info.decls; + val newStats = new ListBuffer[Tree] var e = scope.elems; while ((e ne null) && e.owner == scope) { + + // check no double def var e1 = scope.lookupNextEntry(e); while ((e1 ne null) && e1.owner == scope) { if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) && @@ -1527,12 +1549,23 @@ trait Typers { self: Analyzer => {if(!settings.debug.value) "" else " in "+unit.toString}) e1 = scope.lookupNextEntry(e1); } + + // add synthetics + synthetics get e.sym match { + case Some(tree) => + newStats += tree + synthetics -= e.sym + case None => + } + e = e.next } + if (newStats.isEmpty) stats + else stats ::: (newStats.toList map typedStat) } val result = List.mapConserve(stats)(typedStat) - if (!phase.erasedTypes) checkNoDoubleDefs(result) - result + if (phase.erasedTypes) result + else checkNoDoubleDefsAndAddSynthetics(result) } def typedArg(arg: Tree, mode: Int, newmode: Int, pt: Type): Tree = @@ -1571,13 +1604,11 @@ trait Typers { self: Analyzer => val argtypes = args map (arg => AllClass.tpe) val pre = fun.symbol.tpe.prefix var sym = fun.symbol filter { alt => - isApplicableSafe(context.undetparams, pre.memberType(alt), argtypes, pt) + isApplicableSafe(context.undetparams, followApply(pre.memberType(alt)), argtypes, pt) } if (sym hasFlag OVERLOADED) { // eliminate functions that would result from tupling transforms - val sym1 = sym filter { alt => - formalTypes(alt.tpe.paramTypes, argtypes.length).length == argtypes.length - } + val sym1 = sym filter (alt => hasExactlyNumParams(followApply(alt.tpe), argtypes.length)) if (sym1 != NoSymbol) sym = sym1 } if (sym != NoSymbol) @@ -1922,6 +1953,7 @@ trait Typers { self: Analyzer => trackSetInfo(quantified setFlag EXISTENTIAL)(bound.cloneInfo(quantified)) } val typeParamTypes = typeParams map (_.tpe) // don't trackSetInfo here, since type already set! + //println("ex trans "+rawSyms+" . "+tp+" "+typeParamTypes+" "+(typeParams map (_.info)))//DEBUG for (tparam <- typeParams) tparam.setInfo(tparam.info.subst(rawSyms, typeParamTypes)) (typeParams, tp.subst(rawSyms, typeParamTypes)) } @@ -2237,7 +2269,9 @@ trait Typers { self: Analyzer => } else { if (!lhs1.tpe.isError) { //println(lhs1+" = "+rhs)//DEBUG - error(tree.pos, "assignment to non-variable ") + error(tree.pos, "assignment to "+ + (if ((varsym ne null) && varsym.isValue) "immutable value" + else "non variable")) } setError(tree) } @@ -2629,7 +2663,6 @@ trait Typers { self: Analyzer => case SelectFromTypeTree(_, _) => copy.SelectFromTypeTree(tree, qual, name) } val result = stabilize(checkAccessible(tree1, sym, qual.tpe, qual), qual.tpe, mode, pt) - if (sym.isCaseFactory && !phase.erasedTypes) checkStable(qual) if (!global.phase.erasedTypes && settings.Xchecknull.value && !sym.isConstructor && !(qual.tpe <:< NotNullClass.tpe) && !qual.tpe.isNotNull) @@ -2676,14 +2709,13 @@ trait Typers { self: Analyzer => var defSym: Symbol = tree.symbol // the directly found symbol var pre: Type = NoPrefix // the prefix type of defSym, if a class member var qual: Tree = EmptyTree // the qualififier tree if transformed tree is a select - // if we are in a constructor of a pattern, ignore all methods - // which are not case factories (note if we don't do that + + // if we are in a constructor of a pattern, ignore all definitions + // which are methods (note: if we don't do that // case x :: xs in class List would return the :: method). def qualifies(sym: Symbol): Boolean = sym.exists && - ((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || - !sym.isSourceMethod || sym.isCaseFactory) - + ((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || !sym.isSourceMethod) if (defSym == NoSymbol) { var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope @@ -2795,8 +2827,7 @@ trait Typers { self: Analyzer => if (inIDE) { Ident(defSym.name) setType tree1.tpe setSymbol defSym setPos tree.pos } else tree1 - } - else { + } else { var tree1 = if (qual == EmptyTree) tree else atPos(tree.pos)(Select(qual, name)) // atPos necessary because qualifier might come from startContext @@ -3380,7 +3411,7 @@ trait Typers { self: Analyzer => def improves(info1: ImplicitInfo, info2: ImplicitInfo) = (info2 == NoImplicitInfo) || (info1 != NoImplicitInfo) && - isStrictlyBetterExpr(info1.tpe, info2.tpe) + isStrictlyMoreSpecific(info1.tpe, info2.tpe) val shadowed = new HashSet[Name](8) def isApplicable(info: ImplicitInfo): Boolean = !containsError(info.tpe) && diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index 98c6935953..c0be7a9454 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -6,6 +6,8 @@ package scala.tools.nsc.typechecker +import symtab.Flags._ + /* * @author Martin Odersky * @version 1.0 @@ -14,6 +16,7 @@ trait Unapplies { self: Analyzer => import global._ import definitions._ + import posAssigner.atPos /** returns type list for return type of the extraction */ def unapplyTypeList(ufn: Symbol, ufntpe: Type) = { @@ -79,7 +82,6 @@ trait Unapplies { self: Analyzer => else productType({val es = elems; if(useWildCards) elems map { x => WildcardType} else elems}) */ - def unapplyReturnTypeExpected(argsLength: Int) = argsLength match { case 0 => BooleanClass.tpe case 1 => optionType(WildcardType) @@ -92,4 +94,88 @@ trait Unapplies { self: Analyzer => if (unapp == NoSymbol) unapp = tp.member(nme.unapplySeq) unapp } + + private def copyUntyped[T <: Tree](tree: T): T = { + val tree1 = tree.duplicate + UnTyper.traverse(tree1) + tree1 + } + + private def classType(cdef: ClassDef, tparams: List[TypeDef]): Tree = { + val tycon = gen.mkAttributedRef(cdef.symbol) + if (tparams.isEmpty) tycon else AppliedTypeTree(tycon, tparams map (x => Ident(x.name))) + } + + private def constrParams(cdef: ClassDef): List[List[ValDef]] = { + val constr = treeInfo.firstConstructor(cdef.impl.body) + (constr: @unchecked) match { + case DefDef(_, _, _, vparamss, _, _) => vparamss map (_ map copyUntyped[ValDef]) + } + } + + /** The return value of an unapply method of a case class C[Ts] + * @param param The name of the parameter of the unapply method, assumed to be of type C[Ts] + * @param caseclazz The case class C[Ts] + */ + private def caseClassUnapplyReturnValue(param: Name, caseclazz: Symbol) = { + def caseFieldAccessorValue(selector: Symbol) = Select(Ident(param), selector) + val accessors = caseclazz.caseFieldAccessors + if (accessors.isEmpty) Literal(true) + else if (accessors.tail.isEmpty) caseFieldAccessorValue(accessors.head) + else Apply(gen.scalaDot(newTermName( "Tuple" + accessors.length)), accessors map caseFieldAccessorValue) + } + + /** The module corresponding to a case class; without any member definitions + */ + def caseModuleDef(cdef: ClassDef): ModuleDef = atPos(cdef.pos) { + var parents = List(gen.scalaScalaObjectConstr) + if (cdef.tparams.isEmpty && constrParams(cdef).length == 1) + parents = gen.scalaFunctionConstr(constrParams(cdef).head map (_.tpt), + Ident(cdef.name)) :: parents + ModuleDef( + Modifiers(cdef.mods.flags & AccessFlags | SYNTHETIC, cdef.mods.privateWithin), + cdef.name.toTermName, + Template(parents, emptyValDef, Modifiers(0), List(), List(List()), List())) + } + + /** The apply method corresponding to a case class + */ + def caseModuleApplyMeth(cdef: ClassDef): DefDef = { + val tparams = cdef.tparams map copyUntyped[TypeDef] + def paramToArg(param: ValDef) = { + val id = Ident(param.name) + val RP = nme.REPEATED_PARAM_CLASS_NAME.toTypeName + param.tpt match { + case AppliedTypeTree(Select(_, RP), _) => Typed(id, Ident(nme.WILDCARD_STAR.toTypeName)) + case _ =>id + } + } + val cparams = constrParams(cdef) + atPos(cdef.pos) { + DefDef( + Modifiers(SYNTHETIC | CASE), + nme.apply, + tparams, + cparams, + classType(cdef, tparams), + New(classType(cdef, tparams), cparams map (_ map paramToArg))) + } + } + + /** The unapply method corresponding to a case class + */ + def caseModuleUnapplyMeth(cdef: ClassDef): DefDef = { + val tparams = cdef.tparams map copyUntyped[TypeDef] + val unapplyParamName = newTermName("x$0") + atPos(cdef.pos) { + DefDef( + Modifiers(SYNTHETIC | CASE), + nme.unapply, + tparams, + List(List(ValDef(Modifiers(PARAM | SYNTHETIC), unapplyParamName, + classType(cdef, tparams), EmptyTree))), + TypeTree(), + caseClassUnapplyReturnValue(unapplyParamName, cdef.symbol)) + } + } } diff --git a/src/library/scala/collection/jcl/SortedSet.scala b/src/library/scala/collection/jcl/SortedSet.scala index d1317096ad..0e59eb5c43 100644 --- a/src/library/scala/collection/jcl/SortedSet.scala +++ b/src/library/scala/collection/jcl/SortedSet.scala @@ -9,6 +9,7 @@ // $Id$ package scala.collection.jcl; +import Predef._ object SortedSet { trait Projection[A] extends Set.Projection[A] with SortedSet[A] { @@ -49,7 +50,8 @@ trait SortedSet[A] extends scala.collection.SortedSet[A] with jcl.Set[A] with So override def has(a : A) : Boolean = SortedSet.this.has(a) } - protected class Filter(p : A => Boolean) extends super.Filter(p) with SortedSet.Projection[A] { + protected class Filter(pp : A => Boolean) extends super.Filter(pp) with SortedSet.Projection[A] { + override def p(a : A) = pp(a) def compare(a0 : A, a1 : A) : Int = SortedSet.this.compare(a0, a1); override def filter(p0 : A => Boolean) = SortedSet.this.projection.filter(k => p(k) && p0(k)); } diff --git a/test/files/jvm/serialization.check b/test/files/jvm/serialization.check new file mode 100755 index 0000000000..144e31603f --- /dev/null +++ b/test/files/jvm/serialization.check @@ -0,0 +1,146 @@ +x1 = List() +y1 = List() +x1 eq y1: true - y1 eq x1: true + +x2 = None +y2 = None +x2 eq y2: true - y2 eq x2: true + +x3 = Array[1,2,3] +y3 = Array[1,2,3] +arrayEquals(x3, y3): true + +x4 = +y4 = +x4(2): 4 - y4(2): 4 + +x = List((buffers,20), (layers,2), (title,3)) +y = List((buffers,20), (layers,2), (title,3)) +x equals y: true - y equals x: true + +x = Map(buffers -> 20, layers -> 2, title -> 3) +y = Map(buffers -> 20, layers -> 2, title -> 3) +x equals y: true - y equals x: true + +x = Set(2, 3) +y = Set(2, 3) +x equals y: true - y equals x: true + +x = Set(5, 3) +y = Set(5, 3) +x equals y: true - y equals x: true + +x = Queue(a,b,c) +y = Queue(a,b,c) +x equals y: true - y equals x: true + +x = Stack(c, b, a) +y = Stack(c, b, a) +x equals y: true - y equals x: true + +x = Map(42 -> FortyTwo) +y = Map(42 -> FortyTwo) +x equals y: true - y equals x: true + +x = Set(0, 2) +y = Set(0, 2) +x equals y: true - y equals x: true + +x = ArrayBuffer(one, two) +y = ArrayBuffer(one, two) +x equals y: true - y equals x: true + +x = Map(title -> 3, buffers -> 20, layers -> 2) +y = Map(title -> 3, buffers -> 20, layers -> 2) +x equals y: true - y equals x: true + +x = Set(0, 8, 9) +y = Set(0, 8, 9) +x equals y: true - y equals x: true + +x = Set(layers, buffers, title) +y = Set(layers, buffers, title) +x equals y: true - y equals x: true + +x = LinkedList(2, 3) +y = LinkedList(2, 3) +x equals y: true - y equals x: true + +x = Queue(20, 2, 3) +y = Queue(20, 2, 3) +x equals y: true - y equals x: true + +x = Stack(20, 2, 3) +y = Stack(20, 2, 3) +x equals y: true - y equals x: true + +x = ListBuffer(white, black) +y = ListBuffer(white, black) +x equals y: true - y equals x: true + +x = title +y = title +x equals y: true - y equals x: true + +x = + + + + + + + + + + + + + + + + +
Last NameFirst Name
Tom 20
Bob 22
James 19
+ + +y = + + + + + + + + + + + + + + + + +
Last NameFirst Name
Tom 20
Bob 22
James 19
+ + +x equals y: true - y equals x: true + +x = Tim +y = Tim +x equals y: true - y equals x: true + +x = Bob +y = Bob +x equals y: true - y equals x: true + +x = John +y = John +x equals y: true - y equals x: true + +x = Bill +y = Bill +x equals y: true - y equals x: true + +x = Paul +y = Paul +x equals y: true - y equals x: true + diff --git a/test/files/jvm/serialization.scala b/test/files/jvm/serialization.scala new file mode 100755 index 0000000000..3049d7815b --- /dev/null +++ b/test/files/jvm/serialization.scala @@ -0,0 +1,345 @@ +//############################################################################ +// Serialization +//############################################################################ +// $Id: serialization.scala 12990 2007-10-03 16:52:05Z michelou $ + +import java.lang.System + +object EqualityTest { + def check[A, B](x: A, y: B) { + println("x = " + x) + println("y = " + y) + println("x equals y: " + (x equals y) + " - y equals x: " + (y equals x)) + println() + } +} + +object Serialize { + @throws(classOf[java.io.IOException]) + def write[A](o: A): Array[Byte] = { + val ba = new java.io.ByteArrayOutputStream(512) + val out = new java.io.ObjectOutputStream(ba) + out.writeObject(o) + out.close() + ba.toByteArray() + } + @throws(classOf[java.io.IOException]) + @throws(classOf[ClassNotFoundException]) + def read[A](buffer: Array[Byte]): A = { + val in = + new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(buffer)) + in.readObject().asInstanceOf[A] + } +} + +//############################################################################ +// Test classes in package "scala" + +@serializable +object Test1_scala { + + private def arrayToString[A](arr: Array[A]): String = + List.fromArray(arr).mkString("Array[",",","]") + + private def arrayEquals[A, B](a1: Array[A], a2: Array[B]) = + (a1.length == a2.length) && + (Iterator.range(0, a1.length) forall { i => a1(i) == a2(i) }) + + val x1 = Nil + val x2 = None + val x3 = Array(1, 2, 3) + val x4 = { x: Int => 2 * x } + + try { + val y1: List[Nothing] = Serialize.read(Serialize.write(x1)) + val y2: Option[Nothing] = Serialize.read(Serialize.write(x2)) + val y3: Array[Int] = Serialize.read(Serialize.write(x3)) + val y4: Function[Int, Int] = Serialize.read(Serialize.write(x4)) + + println("x1 = " + x1) + println("y1 = " + y1) + println("x1 eq y1: " + (x1 eq y1) + " - y1 eq x1: " + (y1 eq x1)) + println + println("x2 = " + x2) + println("y2 = " + y2) + println("x2 eq y2: " + (x2 eq y2) + " - y2 eq x2: " + (y2 eq x2)) + println + println("x3 = " + arrayToString(x3)) + println("y3 = " + arrayToString(y3)) + println("arrayEquals(x3, y3): " + arrayEquals(x3, y3)) + println + println("x4 = ") + println("y4 = ") + println("x4(2): " + x4(2) + " - y4(2): " + y4(2)) + println + } + catch { + case e: Exception => + e.printStackTrace() + println("Error in Test1_scala: " + e) + } +} + +//############################################################################ +// Test classes in package "scala.collection.immutable" + +@serializable +object Test2_immutable { + import scala.collection.immutable.{ + BitSet, ListMap, ListSet, Queue, Stack, TreeSet, TreeMap} + + val x1 = List( + Pair("buffers", 20), + Pair("layers", 2), + Pair("title", 3) + ) + + val x2 = new ListMap[String, Int] + .incl(Pair("buffers", 20)) + .incl(Pair("layers", 2)) + .incl(Pair("title", 3)) + + val x3 = { + val bs = new collection.mutable.BitSet() + bs += 2; bs += 3 + bs.toImmutable + } + + val x4 = new ListSet[Int]().incl(3).incl(5) + + val x5 = new Queue("a", "b", "c") + + val x6 = new Stack().push("a", "b", "c") + + val x7 = new TreeMap[Int, String] + 42 -> "FortyTwo" + + val x8 = new TreeSet[Int]().incl(2).incl(0) + + try { + val y1: List[Pair[String, Int]] = Serialize.read(Serialize.write(x1)) + val y2: ListMap[String, Int] = Serialize.read(Serialize.write(x2)) + val y3: BitSet = Serialize.read(Serialize.write(x3)) + val y4: ListSet[Int] = Serialize.read(Serialize.write(x4)) + val y5: Queue[String] = Serialize.read(Serialize.write(x5)) + val y6: Stack[String] = Serialize.read(Serialize.write(x6)) + val y7: TreeMap[Int, String] = Serialize.read(Serialize.write(x7)) + val y8: TreeSet[Int] = Serialize.read(Serialize.write(x8)) + + EqualityTest.check(x1, y1) + EqualityTest.check(x2, y2) + EqualityTest.check(x3, y3) + EqualityTest.check(x4, y4) + EqualityTest.check(x5, y5) + EqualityTest.check(x6, y6) + EqualityTest.check(x7, y7) + EqualityTest.check(x8, y8) + } + catch { + case e: Exception => + println("Error in Test2_immutable: " + e) + throw e + } +} + +//############################################################################ +// Test classes in package "scala.collection.mutable" + +object Test3_mutable { + import scala.collection.mutable.{ + ArrayBuffer, BitSet, HashMap, HashSet, History, LinkedList, ListBuffer, + Publisher, Queue, RevertableHistory, Stack} + + val x0 = new ArrayBuffer[String] + x0 ++= List("one", "two") + + val x2 = new BitSet() + x2 += 0 + x2 += 8 + x2 += 9 + + val x1 = new HashMap[String, Int] + x1 ++= Test2_immutable.x1 + + val x3 = new HashSet[String] + x3 ++= Test2_immutable.x1.map(p => p._1) + + @serializable + class Feed extends Publisher[String, Feed] + + val x8 = new History[String, Feed] + + val x4 = new LinkedList[Int](2, null) + x4.append(new LinkedList(3, null)) + + val x7 = new ListBuffer[String] + x7 ++= List("white", "black") + + val x5 = new Queue[Int] + x5 ++= Test2_immutable.x1.map(p => p._2) + + val x6 = new Stack[Int] + x6 ++= x5 + + try { + val y0: ArrayBuffer[String] = Serialize.read(Serialize.write(x0)) + val y1: HashMap[String, Int] = Serialize.read(Serialize.write(x1)) + val y2: BitSet = Serialize.read(Serialize.write(x2)) + val y3: HashSet[String] = Serialize.read(Serialize.write(x3)) + val y4: LinkedList[Int] = Serialize.read(Serialize.write(x4)) + val y5: Queue[Int] = Serialize.read(Serialize.write(x5)) + val y6: Stack[Int] = Serialize.read(Serialize.write(x6)) + val y7: ListBuffer[String] = Serialize.read(Serialize.write(x7)) + val y8: History[String, Feed] = Serialize.read(Serialize.write(x8)) + + EqualityTest.check(x0, y0) + EqualityTest.check(x1, y1) + EqualityTest.check(x2, y2) + EqualityTest.check(x3, y3) + EqualityTest.check(x4, y4) + EqualityTest.check(x5, y5) + EqualityTest.check(x6, y6) + EqualityTest.check(x7, y7) + //EqualityTest.check(x8, y8) //todo + } + catch { + case e: Exception => + println("Error in Test3_mutable: " + e) + } +} + +//############################################################################ +// Test classes in package "scala.xml" + +object Test4_xml { + import scala.xml.Elem + + val x1 = title; + + case class Person(name: String, age: Int) + + class AddressBook(a: Person*) { + private val people: List[Person] = a.toList + def toXHTML = + + + + + + { for (val p <- people) yield + + + + } +
Last NameFirst Name
{ p.name } { p.age.toString() }
; + } + + val people = new AddressBook( + Person("Tom", 20), + Person("Bob", 22), + Person("James", 19)) + + val x2 = + + + { people.toXHTML } + + ; + + try { + val y1: scala.xml.Elem = Serialize.read(Serialize.write(x1)) + val y2: scala.xml.Elem = Serialize.read(Serialize.write(x2)) + + EqualityTest.check(x1, y1) + EqualityTest.check(x2, y2) + } + catch { + case e: Exception => + println("Error in Test4_xml: " + e) + } +} + +//############################################################################ +// Test user-defined classes WITHOUT nesting + +@serializable +class Person(_name: String) { + private var name = _name + override def toString() = name + override def equals(that: Any): Boolean = + that.isInstanceOf[Person] && + (name == that.asInstanceOf[Person].name) +} + +@serializable +class Employee(_name: String) { + private var name = _name + override def toString() = name +} +@serializable +object bob extends Employee("Bob") + +object Test5 { + val x1 = new Person("Tim") + val x2 = bob + + try { + val y1: Person = Serialize.read(Serialize.write(x1)) + val y2: Employee = Serialize.read(Serialize.write(x2)) + + EqualityTest.check(x1, y1) + EqualityTest.check(x2, y2) + } + catch { + case e: Exception => + println("Error in Test5: " + e) + } +} + +//############################################################################ +// Test user-defined classes WITH nesting + +@serializable +object Test6 { + @serializable + object bill extends Employee("Bill") { + val x = paul + } + @serializable + object paul extends Person("Paul") { + val x = 4 // bill; => StackOverflowException !!! + } + val x1 = new Person("John") + val x2 = bill + val x3 = paul + + try { + val y1: Person = Serialize.read(Serialize.write(x1)) + val y2: Employee = Serialize.read(Serialize.write(x2)) + val y3: Person = Serialize.read(Serialize.write(x3)) + + EqualityTest.check(x1, y1) + EqualityTest.check(x2, y2) + EqualityTest.check(x3, y3) + } + catch { + case e: Exception => + println("Error in Test6: " + e) + } +} + +//############################################################################ +// Test code + +object Test { + def main(args: Array[String]) { + Test1_scala + Test2_immutable + Test3_mutable + Test4_xml + Test5 + Test6 + } +} + +//############################################################################ + diff --git a/test/files/jvm/typerep.check b/test/files/jvm/typerep.check new file mode 100755 index 0000000000..ff98348304 --- /dev/null +++ b/test/files/jvm/typerep.check @@ -0,0 +1,47 @@ +Boolean +Boolean +true +Byte +Char +Int +Long +Float +Double +String +Unit + +Some[Int] +Some[Int] +Some[Some[Int]] +None +None + +List[Int] +List[Int] +List[List[Int]] +Nil +List[Any] + +Array[Int] +Array[Array[Int]] +Array[Int] +Array[Int] +Array[Int] +Array[Int] + +Tuple2[Int, String] +Tuple3[Char, Char, String] +Tuple2[Tuple2[Int, String], Tuple2[Int, String]] +Tuple2[Tuple2[Some[Char], Int], Tuple2[Some[Char], Int]] + +Function1[Int, Int] +Int +Function1[Int, Int] +Int +Function1[Int, Function1[Int, Int]] +Function1[Int, Int] +Int +Function3[Boolean, List[Char], Int, Int] +Function2[Function1[Int, Int], Int, Int] +Int + diff --git a/test/files/jvm/typerep.scala b/test/files/jvm/typerep.scala new file mode 100755 index 0000000000..b133d7ce99 --- /dev/null +++ b/test/files/jvm/typerep.scala @@ -0,0 +1,374 @@ +//############################################################################ +// Type Representation at runtime +//############################################################################ +// $Id: $ + +import TypeRep._ + +object Test extends Application { + testPrimitives + testOptions + testLists + testArrays + testTuples + testFuncs + testClasses +} + +object serialize { + import java.io._ + + @throws(classOf[IOException]) + def write[A](o: A): Array[Byte] = { + val ba = new ByteArrayOutputStream(512) + val out = new ObjectOutputStream(ba) + out.writeObject(o) + out.close() + ba.toByteArray() + } + @throws(classOf[IOException]) + @throws(classOf[ClassNotFoundException]) + def read[A](buffer: Array[Byte]): A = { + val in = + new ObjectInputStream(new ByteArrayInputStream(buffer)) + in.readObject().asInstanceOf[A] + } +} + +object testPrimitives { + println(getType(true)) + val b = false; val bt = getType(b) + println(bt) + val bt1: TypeRep[Boolean] = serialize.read(serialize.write(bt)) + println(bt1 == bt) + println(getType(16.toByte)) + println(getType('a')) + println(getType(3)) + println(getType(3l)) + println(getType(0.0f)) + println(getType(0.0d)) + println(getType("abc")) + println(getType(())) // Unit +// println(getType(classOf[Int])) // Class + println +} + +object testOptions { + println(getType(Some(2))) + val x: Option[Int] = Some(2) + println(getType(x)) + println(getType(Some(Some(3)))) + println(getType(None)) + val y: Option[Int] = None + println(getType(y)) + println +} + +object testLists { + println(getType(List(3))) + println(getType(3 :: Nil)) + println(getType(List(List(3)))) + println(getType(Nil)) + println(getType(List(1, "abc"))) + println +} + +object testArrays { + println(getType(Array(3))) + println(getType(Array(Array(3), Array(4)))) + println(getType(new Array[Int](0))) + println(getType(List(1).toArray)) + println(getType(List[Int]().toArray)) + println(getType(Array(3).drop(1).toArray)) // empty + println +} + +object testTuples { + println(getType((3, "abc"))) + println(getType(Triple('a', 'b', "c"))) + println(getType(((3, "abc"), (4, "xyz")))) + println(getType(((Some('b'), 3), (Some('a'), 4)))) + //println(getType(((Some('b'), 3), (None, 4)))) + println +} + +object testFuncs { + def f1(x: Int): Int = 2 * x + println(getType(f1 _)) + println(getType(f1(2))) + val f2 = (x: Int) => 2 * x + println(getType(f2)) + println(getType(f2(2))) + val f3 = (x: Int) => (y: Int) => x + y + println(getType(f3)) + println(getType(f3(2))) + println(getType(f3(2)(2))) + def f4(b: Boolean, c: List[Char], i: Int): Int = i + println(getType(f4 _)) + def f5(f: Int => Int, x: Int) = f(x) + println(getType(f5 _)) + println(getType(f5(f1, 1))) + println +} + +class Foo { + class Bar(x: Int) +} + + +object foo extends Foo + +package pkg1 { + class C1 + object c1 extends C1 +} + +object testClasses { + /* + case object FooRep extends TypeRep[Foo] { + override def toString = "Foo" + } + implicit def fooRep[A](x: A)(implicit rep: TypeRep[foo.type]): TypeRep[foo.type] = rep + println(getType(foo)) + println(getType(new foo.Bar(0))) + val foo2 = new Foo + println(getType(foo2)) + println(getType(new foo2.Bar(1))) + println + + println(getType(pkg1.c1)) + val c1 = new pkg1.C1 + println(getType(c1)) + println + */ +} + + +/** + * @author Stephane Micheloud + * @version 1.0 + */ +abstract class TypeRep[A] + +object TypeRep { + + def getType[A](x: A)(implicit rep: TypeRep[A]): TypeRep[A] = rep + + def getType[A](x: Option[A])(implicit rep: TypeRep[A]): TypeRep[Option[A]] = (x match { + case Some(v) => SomeRep(rep) + case None => NoneRep // or NoneRep(rep) + }).asInstanceOf[TypeRep[Option[A]]] + + def getType[A](x: List[A])(implicit rep: TypeRep[A]): TypeRep[List[A]] = (x match { + case h :: t => ListRep(getType(h)) + case Nil => NilRep + }).asInstanceOf[TypeRep[List[A]]] + + implicit def boolRep: TypeRep[Boolean] = BooleanRep + implicit def byteRep: TypeRep[Byte] = ByteRep + implicit def charRep: TypeRep[Char] = CharRep + implicit def shortRep: TypeRep[Short] = ShortRep + implicit def intRep: TypeRep[Int] = IntRep + implicit def longRep: TypeRep[Long] = LongRep + implicit def floatRep: TypeRep[Float] = FloatRep + implicit def doubleRep: TypeRep[Double] = DoubleRep + + implicit def unitRep: TypeRep[Unit] = UnitRep +// implicit def classRep: TypeRep[Class] = ClassRep + implicit def stringRep: TypeRep[String] = StringRep + implicit def noneRep: TypeRep[Option[Nothing]] = NoneRep[Nothing](NothingRep.asInstanceOf[TypeRep[Nothing]]) + implicit def anyRep: TypeRep[Any] = AnyRep + implicit def nothingRep: TypeRep[Nothing] = NothingRep + + implicit def someRep[A](implicit elemrep: TypeRep[A]): TypeRep[Some[A]] = + SomeRep(elemrep) + + implicit def listRep[A](implicit elemrep: TypeRep[A]): TypeRep[List[A]] = + ListRep(elemrep) + + implicit def arrayRep[A](implicit elemrep: TypeRep[A]): TypeRep[Array[A]] = + ArrayRep(elemrep) + + implicit def tuple2Rep[A1, A2](implicit _1: TypeRep[A1], _2: TypeRep[A2]): TypeRep[Tuple2[A1, A2]] = + Tuple2Rep(_1, _2) + implicit def tuple3Rep[A1, A2, A3](implicit _1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3]): TypeRep[Tuple3[A1, A2, A3]] = + Tuple3Rep(_1, _2, _3) + implicit def tuple4Rep[A1, A2, A3, A4](implicit _1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4]): TypeRep[Tuple4[A1, A2, A3, A4]] = + Tuple4Rep(_1, _2, _3, _4) + implicit def tuple5Rep[A1, A2, A3, A4, A5](implicit _1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4], _5: TypeRep[A5]): TypeRep[Tuple5[A1, A2, A3, A4, A5]] = + Tuple5Rep(_1, _2, _3, _4, _5) + implicit def tuple6Rep[A1, A2, A3, A4, A5, A6](implicit _1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4], _5: TypeRep[A5], _6: TypeRep[A6]): TypeRep[Tuple6[A1, A2, A3, A4, A5, A6]] = + Tuple6Rep(_1, _2, _3, _4, _5, _6) + implicit def tuple7Rep[A1, A2, A3, A4, A5, A6, A7](implicit _1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4], _5: TypeRep[A5], _6: TypeRep[A6], _7: TypeRep[A7]): TypeRep[Tuple7[A1, A2, A3, A4, A5, A6, A7]] = + Tuple7Rep(_1, _2, _3, _4, _5, _6, _7) + implicit def tuple8Rep[A1, A2, A3, A4, A5, A6, A7, A8](implicit _1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4], _5: TypeRep[A5], _6: TypeRep[A6], _7: TypeRep[A7], _8: TypeRep[A8]): TypeRep[Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]] = + Tuple8Rep(_1, _2, _3, _4, _5, _6, _7, _8) + implicit def tuple9Rep[A1, A2, A3, A4, A5, A6, A7, A8, A9](implicit _1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4], _5: TypeRep[A5], _6: TypeRep[A6], _7: TypeRep[A7], _8: TypeRep[A8], _9: TypeRep[A9]): TypeRep[Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]] = + Tuple9Rep(_1, _2, _3, _4, _5, _6, _7, _8, _9) + + implicit def func1Rep[A1, B](implicit a1: TypeRep[A1], b: TypeRep[B]): TypeRep[Function1[A1, B]] = + Function1Rep(a1, b) + implicit def func2Rep[A1, A2, B](implicit a1: TypeRep[A1], a2: TypeRep[A2], b: TypeRep[B]): TypeRep[Function2[A1, A2, B]] = + Function2Rep(a1, a2, b) + implicit def func3Rep[A1, A2, A3, B](implicit a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], b: TypeRep[B]): TypeRep[Function3[A1, A2, A3, B]] = + Function3Rep(a1, a2, a3, b) + implicit def func4Rep[A1, A2, A3, A4, B](implicit a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], b: TypeRep[B]): TypeRep[Function4[A1, A2, A3, A4, B]] = + Function4Rep(a1, a2, a3, a4, b) + implicit def func5Rep[A1, A2, A3, A4, A5, B](implicit a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], b: TypeRep[B]): TypeRep[Function5[A1, A2, A3, A4, A5, B]] = + Function5Rep(a1, a2, a3, a4, a5, b) + implicit def func6Rep[A1, A2, A3, A4, A5, A6, B](implicit a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], b: TypeRep[B]): TypeRep[Function6[A1, A2, A3, A4, A5, A6, B]] = + Function6Rep(a1, a2, a3, a4, a5, a6, b) + implicit def func7Rep[A1, A2, A3, A4, A5, A6, A7, B](implicit a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], a7: TypeRep[A7], b: TypeRep[B]): TypeRep[Function7[A1, A2, A3, A4, A5, A6, A7, B]] = + Function7Rep(a1, a2, a3, a4, a5, a6, a7, b) + implicit def func8Rep[A1, A2, A3, A4, A5, A6, A7, A8, B](implicit a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], a7: TypeRep[A7], a8: TypeRep[A8], b: TypeRep[B]): TypeRep[Function8[A1, A2, A3, A4, A5, A6, A7, A8, B]] = + Function8Rep(a1, a2, a3, a4, a5, a6, a7, a8, b) + implicit def func9Rep[A1, A2, A3, A4, A5, A6, A7, A8, A9, B](implicit a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], a7: TypeRep[A7], a8: TypeRep[A8], a9: TypeRep[A9], b: TypeRep[B]): TypeRep[Function9[A1, A2, A3, A4, A5, A6, A7, A8, A9, B]] = + Function9Rep(a1, a2, a3, a4, a5, a6, a7, a8, a9, b) +/* + implicit def objectRep[A <: AnyRef](obj: A)(implicit rep: TypeRep[A]): TypeRep[AnyClass] = + ObjectRep(obj.getClass) +*/ + + case object BooleanRep extends TypeRep[Boolean] { + override def toString = "Boolean" + } + case object ByteRep extends TypeRep[Byte] { + override def toString = "Byte" + } + case object CharRep extends TypeRep[Char] { + override def toString = "Char" + } + case object ShortRep extends TypeRep[Short] { + override def toString = "Short" + } + case object IntRep extends TypeRep[Int] { + override def toString = "Int" + } + case object LongRep extends TypeRep[Long] { + override def toString = "Long" + } + case object FloatRep extends TypeRep[Float] { + override def toString = "Float" + } + case object DoubleRep extends TypeRep[Double] { + override def toString = "Double" + } + + case object UnitRep extends TypeRep[Unit] { + override def toString = "Unit" + } +// case object ClassRep extends TypeRep[AnyClass] { +// override def toString = "Class" +// } + case object StringRep extends TypeRep[String] { + override def toString = "String" + } + case object NoneRep extends TypeRep[Option[Nothing]] { + override def toString = "None" + } + case object NilRep extends TypeRep[Nil.type] { + override def toString = "Nil" + } + case object AnyRep extends TypeRep[Any] { + override def toString = "Any" + } + case object NothingRep extends TypeRep[Nothing] { + override def toString = "Nothing" + } + + @serializable + case class SomeRep[A](elemRep: TypeRep[A]) extends TypeRep[Some[A]] { + override def toString = "Some[" + elemRep + "]" + } + @serializable + case class NoneRep[A](elemRep: TypeRep[A]) extends TypeRep[Option[A]] { + override def toString = "None[" + elemRep + "]" + } + + @serializable + case class ListRep[A](elemRep: TypeRep[A]) extends TypeRep[List[A]] { + override def toString = "List[" + elemRep + "]" + } + + @serializable + case class ArrayRep[A](elemRep: TypeRep[A]) extends TypeRep[Array[A]] { + override def toString = "Array[" + elemRep + "]" + } + + @serializable + case class Tuple2Rep[A1, A2](_1: TypeRep[A1], _2: TypeRep[A2]) extends TypeRep[Tuple2[A1, A2]] { + override def toString = "Tuple2[" + _1 + ", " + _2 + "]" + } + @serializable + case class Tuple3Rep[A1, A2, A3](_1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3]) extends TypeRep[Tuple3[A1, A2, A3]] { + override def toString = "Tuple3[" + _1 + ", " + _2 + ", " + _3 + "]" + } + @serializable + case class Tuple4Rep[A1, A2, A3, A4](_1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4]) extends TypeRep[Tuple4[A1, A2, A3, A4]] { + override def toString = "Tuple4[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + "]" + } + @serializable + case class Tuple5Rep[A1, A2, A3, A4, A5](_1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4], _5: TypeRep[A5]) extends TypeRep[Tuple5[A1, A2, A3, A4, A5]] { + override def toString = "Tuple5[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + "]" + } + @serializable + case class Tuple6Rep[A1, A2, A3, A4, A5, A6](val _1: TypeRep[A1], val _2: TypeRep[A2], val _3: TypeRep[A3], val _4: TypeRep[A4], val _5: TypeRep[A5], val _6: TypeRep[A6]) extends TypeRep[Tuple6[A1, A2, A3, A4, A5, A6]] { + override def toString = "Tuple6[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + "]" + } + @serializable + case class Tuple7Rep[A1, A2, A3, A4, A5, A6, A7](val _1: TypeRep[A1], val _2: TypeRep[A2], val _3: TypeRep[A3], val _4: TypeRep[A4], val _5: TypeRep[A5], val _6: TypeRep[A6], val _7: TypeRep[A7]) extends TypeRep[Tuple7[A1, A2, A3, A4, A5, A6, A7]] { + override def toString = "Tuple7[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + ", " + _7 + "]" + } + @serializable + case class Tuple8Rep[A1, A2, A3, A4, A5, A6, A7, A8](val _1: TypeRep[A1], val _2: TypeRep[A2], val _3: TypeRep[A3], val _4: TypeRep[A4], val _5: TypeRep[A5], val _6: TypeRep[A6], val _7: TypeRep[A7], val _8: TypeRep[A8]) extends TypeRep[Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]] { + override def toString = "Tuple8[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + ", " + _7 + ", " + _8 + "]" + } + @serializable + case class Tuple9Rep[A1, A2, A3, A4, A5, A6, A7, A8, A9](val _1: TypeRep[A1], val _2: TypeRep[A2], val _3: TypeRep[A3], val _4: TypeRep[A4], val _5: TypeRep[A5], val _6: TypeRep[A6], val _7: TypeRep[A7], val _8: TypeRep[A8], val _9: TypeRep[A9]) extends TypeRep[Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]] { + override def toString = "Tuple9[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + ", " + _7 + ", " + _8 + ", " + _9 + "]" + } + + @serializable + case class Function1Rep[A1, B](a1: TypeRep[A1], b: TypeRep[B]) extends TypeRep[Function1[A1, B]] { + override def toString = "Function1[" + a1 + ", " + b + "]" + } + @serializable + case class Function2Rep[A1, A2, B](a1: TypeRep[A1], a2: TypeRep[A2], b: TypeRep[B]) extends TypeRep[Function2[A1, A2, B]] { + override def toString = "Function2[" + a1 + ", " + a2 + ", " + b + "]" + } + @serializable + case class Function3Rep[A1, A2, A3, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], b: TypeRep[B]) extends TypeRep[Function3[A1, A2, A3, B]] { + override def toString = "Function3[" + a1 + ", " + a2 + ", " + a3 + ", " + b + "]" + } + @serializable + case class Function4Rep[A1, A2, A3, A4, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], b: TypeRep[B]) extends TypeRep[Function4[A1, A2, A3, A4, B]] { + override def toString = "Function4[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + b + "]" + } + @serializable + case class Function5Rep[A1, A2, A3, A4, A5, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], b: TypeRep[B]) extends TypeRep[Function5[A1, A2, A3, A4, A5, B]] { + override def toString = "Function5[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + b + "]" + } + @serializable + case class Function6Rep[A1, A2, A3, A4, A5, A6, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], b: TypeRep[B]) extends TypeRep[Function6[A1, A2, A3, A4, A5, A6, B]] { + override def toString = "Function6[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + a6 + ", " + b + "]" + } + @serializable + case class Function7Rep[A1, A2, A3, A4, A5, A6, A7, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], a7: TypeRep[A7], b: TypeRep[B]) extends TypeRep[Function7[A1, A2, A3, A4, A5, A6, A7, B]] { + override def toString = "Function7[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + a6 + ", " + a7 + ", " + b + "]" + } + @serializable + case class Function8Rep[A1, A2, A3, A4, A5, A6, A7, A8, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], a7: TypeRep[A7], a8: TypeRep[A8], b: TypeRep[B]) extends TypeRep[Function8[A1, A2, A3, A4, A5, A6, A7, A8, B]] { + override def toString = "Function8[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + a6 + ", " + a7 + ", " + a8 + b + "]" + } + @serializable + case class Function9Rep[A1, A2, A3, A4, A5, A6, A7, A8, A9, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], a7: TypeRep[A7], a8: TypeRep[A8], a9: TypeRep[A9], b: TypeRep[B]) extends TypeRep[Function9[A1, A2, A3, A4, A5, A6, A7, A8, A9, B]] { + override def toString = "Function9[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + a6 + ", " + a7 + ", " + a8 + ", " + b + "]" + } +/* + @serializable + case class ObjectRep[A](c: Class) extends TypeRep[A] { + override def toString = c.getName + } +*/ +} + diff --git a/test/files/neg/bug414.check b/test/files/neg/bug414.check index 67b467ce5d..3396a803f1 100644 --- a/test/files/neg/bug414.check +++ b/test/files/neg/bug414.check @@ -1,4 +1,6 @@ -bug414.scala:5: error: stable identifier required, but Empty found. +bug414.scala:5: error: pattern type is incompatibe with expected type; + found : object Empty + required: IntMap[a] case Empty => ^ bug414.scala:7: error: type mismatch; diff --git a/test/files/neg/bug692.check b/test/files/neg/bug692.check index 6eb9f7d8af..308048b80a 100644 --- a/test/files/neg/bug692.check +++ b/test/files/neg/bug692.check @@ -2,7 +2,7 @@ bug692.scala:3: error: not found: type T trait Type[T0] extends Type0[T]; ^ bug692.scala:10: error: class Foo takes type parameters - case class FooType extends ClassType[Foo,AnyRef](ObjectType); + case class FooType extends ClassType[Foo,AnyRef](ObjectType()); ^ bug692.scala:13: error: class Foo takes type parameters case class BarType[T3 <: Foo](tpeT : RefType[T3]) extends ClassType[Bar[T3],Foo](FooType); diff --git a/test/files/neg/bug692.scala b/test/files/neg/bug692.scala index dc5a9040a0..184a14b4b6 100644 --- a/test/files/neg/bug692.scala +++ b/test/files/neg/bug692.scala @@ -7,7 +7,7 @@ abstract class test3 { abstract class ClassType[C <: Z, Z <: AnyRef](zuper : RefType[Z]) extends RefType[C]; - case class FooType extends ClassType[Foo,AnyRef](ObjectType); + case class FooType extends ClassType[Foo,AnyRef](ObjectType()); implicit def typeOfFoo = FooType(); case class BarType[T3 <: Foo](tpeT : RefType[T3]) extends ClassType[Bar[T3],Foo](FooType); diff --git a/test/files/neg/bug783.check b/test/files/neg/bug783.check index a7f978ad06..19e3ead2a9 100644 --- a/test/files/neg/bug783.check +++ b/test/files/neg/bug783.check @@ -1,4 +1,6 @@ -bug783.scala:12: error: stable identifier required, but Contexts.this.globalInit0 found. +bug783.scala:12: error: type mismatch; + found : Contexts.this.Global#Template + required: Contexts.this.global.Template globalInit0.Template(10, 20); - ^ + ^ one error found diff --git a/test/files/neg/bug960.check b/test/files/neg/bug960.check index c947223aa3..e61394f2d0 100644 --- a/test/files/neg/bug960.check +++ b/test/files/neg/bug960.check @@ -1,4 +1,7 @@ -bug960.scala:18: error: cannot resolve overloaded unapply +bug960.scala:18: error: ambiguous reference to overloaded definition, +both method unapply in object List of type [a](List[a])Option[Null] +and method unapply in object List of type [a](List[a])Option[(a, List[a])] +match argument types (List[a]) case List(x, xs) => 7 ^ bug960.scala:12: error: method unapply is defined twice diff --git a/test/files/neg/bug961.scala b/test/files/neg/bug961.scala index eb1620abe1..15309b96b4 100755 --- a/test/files/neg/bug961.scala +++ b/test/files/neg/bug961.scala @@ -2,7 +2,7 @@ object Temp{ abstract class A object B{ private case class B_inner extends A - def apply: A = B_inner + def apply: A = B_inner() def unapply(a: A) = a match { case B_inner() => true case _ => false diff --git a/test/files/neg/scopes.check b/test/files/neg/scopes.check index 13f728b01c..bb8e15058b 100644 --- a/test/files/neg/scopes.check +++ b/test/files/neg/scopes.check @@ -22,4 +22,9 @@ scopes.scala:15: error: x is already defined as value x scopes.scala:17: error: x is already defined as value x case x::x => x ^ -8 errors found +scopes.scala:1: error: type mismatch; + found : float + required: int +case class test0(x: int, x: float) + ^ +9 errors found diff --git a/test/files/pos/bug432.scala b/test/files/pos/bug432.scala new file mode 100644 index 0000000000..8e3097ac9d --- /dev/null +++ b/test/files/pos/bug432.scala @@ -0,0 +1,2 @@ +case class Tata +object Tata diff --git a/test/files/run/bug874.scala b/test/files/run/bug874.scala deleted file mode 100644 index 945a5bf620..0000000000 --- a/test/files/run/bug874.scala +++ /dev/null @@ -1,22 +0,0 @@ -object Test { - abstract class Base { - type T; - def T : T; - def U[A](x1: A)(x2: int): Any - T; - U("xyz")(2) - } - class Mix extends Base { - case class T { - Console.println("T created") - } - case class U[A](x1: A)(x2: int) { - Console.println("U created with "+x1+" and "+x2) - } - } - def main(args : Array[String]) : Unit = { - val obvious: Base = new Mix; - obvious.T - obvious.U("abc")(1) - } -} diff --git a/test/files/run/caseclasses.check b/test/files/run/caseclasses.check index d86bac9de5..7eb54ea631 100644 --- a/test/files/run/caseclasses.check +++ b/test/files/run/caseclasses.check @@ -1 +1,3 @@ OK +creating C(hi) +OK diff --git a/test/files/run/caseclasses.scala b/test/files/run/caseclasses.scala index 72a7232d8a..8cba990114 100644 --- a/test/files/run/caseclasses.scala +++ b/test/files/run/caseclasses.scala @@ -2,6 +2,16 @@ case class Foo(x: int)(y: int); case class Bar; +object M { + abstract case class C(x: String) {} + object C extends (String => C) { + def apply(x: String): C = { + println("creating C("+x+")") + new C(x) {} + } + } +} + object Test extends Application { def fn[a,b](x: a => b) = x; @@ -18,6 +28,11 @@ object Test extends Application { case x:IndexOutOfBoundsException => } + M.C("hi") match { + case M.C("hi") => println("OK") + case _ => println("NO") + } + try { f(2) productElement 3 throw new NullPointerException("duh") diff --git a/test/files/run/classof.check b/test/files/run/classof.check new file mode 100644 index 0000000000..e9a8fd6b76 --- /dev/null +++ b/test/files/run/classof.check @@ -0,0 +1 @@ +SomeClass diff --git a/test/files/run/classof.scala b/test/files/run/classof.scala new file mode 100755 index 0000000000..5c920d797f --- /dev/null +++ b/test/files/run/classof.scala @@ -0,0 +1,8 @@ +class SomeClass + +object Test { + def main(args: Array[String]): Unit = { + val cls: Predef.Class[SomeClass] = classOf[SomeClass] + Console.println(cls.getName()) + } +} diff --git a/test/pending/run/bug874.scala b/test/pending/run/bug874.scala new file mode 100755 index 0000000000..29dfabe0e9 --- /dev/null +++ b/test/pending/run/bug874.scala @@ -0,0 +1,17 @@ +object Test { + abstract class Base { + val U: { + def apply[A](x1: A)(x2: int): Any + } + U("xyz")(2) + } + class Mix extends Base { + case class U[A](x1: A)(x2: int) { + Console.println("U created with "+x1+" and "+x2) + } + } + def main(args : Array[String]) : Unit = { + val obvious: Base = new Mix; + obvious.U("abc")(1) + } +} diff --git a/test/pending/run/classof.check b/test/pending/run/classof.check deleted file mode 100644 index e9a8fd6b76..0000000000 --- a/test/pending/run/classof.check +++ /dev/null @@ -1 +0,0 @@ -SomeClass diff --git a/test/pending/run/classof.scala b/test/pending/run/classof.scala deleted file mode 100644 index b547e5c8c3..0000000000 --- a/test/pending/run/classof.scala +++ /dev/null @@ -1,8 +0,0 @@ -class SomeClass - -object Test { - def main(args: Array[String]): Unit = { - val cls: Class[SomeClass] = classOf[SomeClass] - Console.println(cls.getName()) - } -} -- cgit v1.2.3