diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/Trees.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/Members.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 59 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Definitions.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/CleanUp.scala | 145 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 4 | ||||
-rw-r--r-- | test/files/run/SymbolsTest.scala | 266 | ||||
-rw-r--r-- | test/files/run/priorityQueue.scala | 3 |
9 files changed, 484 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 373859b836..dbbb306130 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -135,7 +135,7 @@ trait Trees { */ def setType(tp: Type): this.type = { /*assert(kindingIrrelevant(tp) || !kindStar || !tp.isHigherKinded, - tp+" should not be higher-kinded");*/ + tp+" should not be higher-kinded"); */ tpe = tp this } diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index 35eeec316e..65616c9a1f 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -113,6 +113,11 @@ trait Members { self: ICodes => def lookupField(s: Symbol) = fields find (_.symbol == s) def lookupMethod(s: Symbol) = methods find (_.symbol == s) def lookupMethod(s: Name) = methods find (_.symbol.name == s) + + /* determines whether or not this class contains a static ctor. */ + def containsStaticCtor: Boolean = methods.exists(_.isStaticCtor) // alex + /* returns this methods static ctor if it has one. */ + def lookupStaticCtor: Option[IMethod] = methods.find(_.isStaticCtor) // alex } /** Represent a field in ICode */ @@ -193,6 +198,9 @@ trait Members { self: ICodes => def isStatic: Boolean = symbol.isStaticMember + /* determines whether or not this method is the class static constructor. */ + def isStaticCtor: Boolean = isStatic && symbol.rawname == nme.CONSTRUCTOR + override def toString() = symbol.fullNameString import opcodes._ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 9abd29cd0a..15852b61d3 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -203,7 +203,7 @@ abstract class GenJVM extends SubComponent { if (isStaticModule(c.symbol) || serialVUID != None || clasz.bootstrapClass.isDefined) { if (isStaticModule(c.symbol)) addModuleInstanceField; - addStaticInit(jclass) + addStaticInit(jclass, c.lookupStaticCtor) if (isTopLevelModule(c.symbol)) { if (c.symbol.linkedClassOfModule == NoSymbol) @@ -214,6 +214,8 @@ abstract class GenJVM extends SubComponent { } } else { + if (c.containsStaticCtor) addStaticInit(jclass, c.lookupStaticCtor) // alex - adds static ctors to class + // it must be a top level class (name contains no $s) def isCandidateForForwarders(sym: Symbol): Boolean = atPhase (currentRun.picklerPhase.next) { @@ -557,6 +559,8 @@ abstract class GenJVM extends SubComponent { } def genMethod(m: IMethod) { + if (m.isStaticCtor) return // alex - skip constructors marked as static, they were handled earlier + log("Generating method " + m.symbol.fullNameString) method = m endPC.clear @@ -668,7 +672,7 @@ abstract class GenJVM extends SubComponent { jclass.getType()) } - def addStaticInit(cls: JClass) { + def addStaticInit(cls: JClass, mopt: Option[IMethod]) { // alex import JAccessFlags._ val clinitMethod = cls.addNewMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", @@ -676,6 +680,53 @@ abstract class GenJVM extends SubComponent { JType.EMPTY_ARRAY, new Array[String](0)) val clinit = clinitMethod.getCode().asInstanceOf[JExtendedCode] + + mopt match { + case Some(m) => + if (clasz.bootstrapClass.isDefined) legacyEmitBootstrapMethodInstall(clinit) + + val oldLastBlock = m.code.blocks.last + val lastBlock = m.code.newBlock + oldLastBlock.replaceInstruction(oldLastBlock.length - 1, JUMP(lastBlock)) + + if (isStaticModule(clasz.symbol)) { + // call object's private ctor from static ctor + lastBlock.emit(NEW(REFERENCE(m.symbol.enclClass))) + lastBlock.emit(CALL_METHOD(m.symbol.enclClass.primaryConstructor, Static(true))) + } + + // add serialVUID code + serialVUID match { + case Some(value) => + import Flags._ + import definitions._ + val fieldName = "serialVersionUID" + val fieldSymbol = clasz.symbol.newValue(NoPosition, newTermName(fieldName)) + .setFlag(STATIC | FINAL) + .setInfo(longType) + clasz.addField(new IField(fieldSymbol)) + lastBlock.emit(CONSTANT(Constant(value))) + lastBlock.emit(STORE_FIELD(fieldSymbol, true)) + case None => () + } + + if (clasz.bootstrapClass.isDefined) { + // emit bootstrap method install + //emitBootstrapMethodInstall(block) + } + + lastBlock.emit(RETURN(UNIT)) + lastBlock.close + + method = m + jmethod = clinitMethod + genCode(m) + case None => + legacyStaticInitializer(cls, clinit) + } + } + + private def legacyStaticInitializer(cls: JClass, clinit: JExtendedCode) { if (isStaticModule(clasz.symbol)) { clinit.emitNEW(cls.getName()) clinit.emitINVOKESPECIAL(cls.getName(), @@ -694,7 +745,7 @@ abstract class GenJVM extends SubComponent { case None => () } - if (clasz.bootstrapClass.isDefined) emitBootstrapMethodInstall(clinit) + if (clasz.bootstrapClass.isDefined) legacyEmitBootstrapMethodInstall(clinit) clinit.emitRETURN() } @@ -702,7 +753,7 @@ abstract class GenJVM extends SubComponent { /** Emit code that installs a boostrap method for invoke dynamic. It installs the default * method, found in scala.runtime.DynamicDispatch. */ - def emitBootstrapMethodInstall(jcode: JExtendedCode) { + def legacyEmitBootstrapMethodInstall(jcode: JExtendedCode) { jcode.emitPUSH(jclass.getType.asInstanceOf[JReferenceType]) jcode.emitPUSH(new JObjectType("scala.runtime.DynamicDispatch")) jcode.emitPUSH("bootstrapInvokeDynamic") diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index 2ba0ee68b9..c8e85edd76 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -128,6 +128,7 @@ trait Definitions { lazy val StringClass = getClass(sn.String) lazy val ClassClass = getClass(sn.Class) def Class_getMethod = getMember(ClassClass, nme.getMethod_) + lazy val SymbolClass = getClass("scala.Symbol") // alex // fundamental modules lazy val PredefModule: Symbol = getModule("scala.Predef") @@ -141,6 +142,7 @@ trait Definitions { def Predef_conforms = getMember(PredefModule, nme.conforms) lazy val ConsoleModule: Symbol = getModule("scala.Console") lazy val ScalaRunTimeModule: Symbol = getModule("scala.runtime.ScalaRunTime") + lazy val SymbolModule: Symbol = getModule("scala.Symbol") // alex def SeqFactory = getMember(ScalaRunTimeModule, nme.Seq) def checkDefinedMethod = getMember(ScalaRunTimeModule, "checkDefined") def isArrayMethod = getMember(ScalaRunTimeModule, "isArray") @@ -246,6 +248,8 @@ trait Definitions { def optionType(tp: Type) = typeRef(OptionClass.typeConstructor.prefix, OptionClass, List(tp)) def someType(tp: Type) = typeRef(SomeClass.typeConstructor.prefix, SomeClass, List(tp)) + def symbolType = typeRef(SymbolClass.typeConstructor.prefix, SymbolClass, List()) // alex + def longType = typeRef(LongClass.typeConstructor.prefix, LongClass, List()) // alex // Product, Tuple, Function private def mkArityArray(name: String, arity: Int, countFrom: Int = 1) = { diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index dcb2097c5f..1634e04025 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -563,14 +563,14 @@ trait Symbols { final def isStaticOwner: Boolean = isPackageClass || isModuleClass && isStatic - /** Is this symbol final?*/ + /** Is this symbol final? */ final def isFinal: Boolean = ( hasFlag(FINAL) || isTerm && ( hasFlag(PRIVATE) || isLocal || owner.isClass && owner.hasFlag(FINAL | MODULE)) ) - /** Is this symbol a sealed class?*/ + /** Is this symbol a sealed class? */ final def isSealed: Boolean = isClass && (hasFlag(SEALED) || isValueClass(this)) diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 444dc42299..556f4d6de4 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -1,5 +1,5 @@ /* NSC -- new Scala compiler - * Copyright 2005-2009 LAMP/EPFL + * Copyrights 2005-2009 LAMP/EPFL * @author Martin Odersky */ // $Id$ @@ -28,6 +28,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { private val newInits = new ListBuffer[Tree] private val classConstantMeth = new HashMap[String, Symbol] + private val symbolStaticFields = new HashMap[String, (Symbol, Tree, Tree)] // alex private var localTyper: analyzer.Typer = null @@ -501,7 +502,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * constructor. */ case Template(parents, self, body) => localTyper = typer.atOwner(tree, currentClass) - if (!forMSIL) { + val transformedTemplate = if (!forMSIL) { // alex - assigned this to a val classConstantMeth.clear newDefs.clear newInits.clear @@ -525,6 +526,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { treeCopy.Template(tree, parents, self, newBody) } else super.transform(tree) + applySymbolFieldInitsToStaticCtor(transformedTemplate.asInstanceOf[Template]) // alex - postprocess to include static ctors case Literal(c) if (c.tag == ClassTag) && !forMSIL=> val tpe = c.typeValue @@ -569,9 +571,148 @@ abstract class CleanUp extends Transform with ast.TreeDSL { } super.transform(tree) + /* + * This transformation should identify Scala symbol invocations in the tree and replace them + * with references to a static member. Also, whenever a class has at least a single symbol invocation + * somewhere in its methods, a new static member should be created and initialized for that symbol. + * For instance, say we have a Scala class: + * + * class Cls { + * // ... + * def someSymbol = `symbolic + * // ... + * } + * + * After transformation, this class looks like this: + * + * class Cls { + * private "static" val <some_name>$symbolic = Symbol("symbolic") + * // ... + * def someSymbol = <some_name>$symbolic + * // ... + * } + * + * The reasoning behind this transformation is the following. Symbols get interned - they are stored + * in a global map which is protected with a lock. The reason for this is making equality checks + * quicker. But calling Symbol.apply, although it does return a unique symbol, accesses a locked object, + * making symbol access slow. To solve this, the unique symbol from the global symbol map in Symbol + * is accessed only once during class loading, and after that, the unique symbol is in the static + * member. Hence, it is cheap to both reach the unique symbol and do equality checks on it. + * + * And, finally, be advised - scala symbol literal and the Symbol class of the compiler + * have little in common. + */ + case symapp @ Apply(Select(Select(a @ Ident(nme.scala_), b @ nme.Symbol), nme.apply), + List(Literal(Constant(symname)))) => // alex + // add the symbol name to a map if it's not there already + val rhs = treeGen.mkCast(Apply(treeGen.scalaDot(nme.Symbol), List(Literal(Constant(symname)))), symbolType) + val (staticFieldSym, sfdef, sfinit) = getSymbolStaticField(symapp.pos, symname.asInstanceOf[String], rhs, symapp) + + // create a reference to a static field + val ntree = typedWithPos(symapp.pos)(REF(staticFieldSym)) + + super.transform(ntree) case _ => super.transform(tree) } + + /* serves as a tree generator */ + object treeGen extends scala.tools.nsc.ast.TreeGen { + val global: CleanUp.this.global.type = CleanUp.this.global + } + + /* Returns the symbol and the tree for the symbol field interning a reference to a symbol 'synmname'. + * If it doesn't exist, i.e. the symbol is encountered the first time, + * it creates a new static field definition and initalization and returns it. + */ + private def getSymbolStaticField(pos: Position, symname: String, rhs: Tree, tree: Tree): (Symbol, Tree, Tree) = { // alex + if (symbolStaticFields.contains(symname)) symbolStaticFields(symname) + else { + val freshname = unit.fresh.newName(pos, "symbol$") + val theTyper = typer.atOwner(tree, currentClass) + + // create a symbol for the static field + val stfieldSym = currentClass.newVariable(pos, freshname) + .setFlag(PRIVATE | STATIC | SYNTHETIC | FINAL) + .setInfo(symbolType) + currentClass.info.decls enter stfieldSym + + // create field definition and initialization + val stfieldDef = theTyper.typed { atPos(pos)(VAL(stfieldSym) === rhs) } + val stfieldInit = theTyper.typed { atPos(pos)(REF(stfieldSym) === rhs) } + + // add field definition to new defs + newDefs append stfieldDef + + symbolStaticFields.put(symname, (stfieldSym, stfieldDef, stfieldInit)) + + symbolStaticFields(symname) + } + } + + /* returns a list of all trees for symbol static fields, and clear the list */ + private def flushSymbolFieldsInitializations: List[Tree] = { + var fieldlst: List[Tree] = Nil + + for ((symbolname, (symbol, deftree, inittree)) <- symbolStaticFields) { + fieldlst ::= inittree + } + symbolStaticFields.clear + + fieldlst + } + + /* finds the static ctor DefDef tree within the template if it exists. */ + def findStaticCtor(template: Template): Option[Tree] = { + template.body.find(_ match { + case defdef @ DefDef(mods, name, tparam, vparam, tp, rhs) => name == nme.CONSTRUCTOR && defdef.symbol.hasFlag(STATIC) + case _ => false + }) + } + + /* changes the template for the class so that it contains a static constructor with symbol fields inits, + * augments an existing static ctor if one already existed. + */ + def applySymbolFieldInitsToStaticCtor(template: Template): Template = { + val symbolInitTrees = flushSymbolFieldsInitializations + if (symbolInitTrees.isEmpty) template + else { + val theTyper = typer.atOwner(template, currentClass) + val newCtor = findStaticCtor(template) match { + // in case there already were static ctors - augment existing ones + // currently, however, static ctors aren't being generated anywhere else + case Some(ctorTree) => + val ctor = ctorTree.asInstanceOf[DefDef] + // modify existing static ctor + val newBlock = ctor.rhs match { + case block @ Block(stats, expr) => + // need to add inits to existing block + treeCopy.Block(block, symbolInitTrees ::: stats, expr) + case term @ _ if term.isInstanceOf[TermTree] => + // need to create a new block with inits and the old term + treeCopy.Block(term, symbolInitTrees, term) + } + treeCopy.DefDef(ctor, ctor.mods, ctor.name, ctor.tparams, ctor.vparamss, ctor.tpt, newBlock) + case None => + // create new static ctor + val staticCtorSym = currentClass.newConstructor(template.pos) + .setFlag(STATIC) + .setInfo(UnitClass.tpe) + val rhs = Block(symbolInitTrees, Literal(())) + val staticCtorTree = DefDef(staticCtorSym, rhs) + theTyper.typed{ atPos(template.pos)(staticCtorTree) } + } + val newTemplate = treeCopy.Template(template, template.parents, template.self, newCtor :: template.body) + //println(newTemplate) + newTemplate + } + } + } // CleanUpTransformer } + + + + + diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index a6d4230969..6347251a5e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1733,7 +1733,7 @@ trait Typers { self: Analyzer => ddef.tpt.setType(tpt1.tpe) val typedMods = removeAnnotations(ddef.mods) var rhs1 = - if (ddef.name == nme.CONSTRUCTOR) { + if (ddef.name == nme.CONSTRUCTOR && !ddef.symbol.hasFlag(STATIC)) { // alex - need this to make it possible to generate static ctors if (!meth.isPrimaryConstructor && (!meth.owner.isClass || meth.owner.isModuleClass || @@ -2861,7 +2861,7 @@ trait Typers { self: Analyzer => * class NPE[T <: NPE[T] @peer] * * (Note: -Yself-in-annots must be on to see the problem) - **/ + * */ val sym = context.owner.newLocalDummy(ann.pos) .newValue(ann.pos, nme.self) diff --git a/test/files/run/SymbolsTest.scala b/test/files/run/SymbolsTest.scala new file mode 100644 index 0000000000..5797aa3b7d --- /dev/null +++ b/test/files/run/SymbolsTest.scala @@ -0,0 +1,266 @@ + + + + +class Slazz { + val s1 = 'myFirstSymbol + val s2 = 'mySecondSymbol + def s3 = 'myThirdSymbol + var s4: Symbol = null + + s4 = 'myFourthSymbol +} + +class Base { + val basesymbol = 'symbase +} + +class Sub extends Base { + val subsymbol = 'symsub +} + +trait Signs { + val ind = 'indication + val trace = 'trace +} + +trait Lazy1 { + lazy val v1 = "lazy v1" + lazy val s1 = 'lazySymbol1 +} + +trait Lazy2 { + lazy val v2 = "lazy v2" + lazy val s2 = 'lazySymbol2 +} + +trait Lazy3 { + lazy val v3 = "lazy v3" + lazy val s3 = 'lazySymbol3 +} + +object SingletonOfLazyness { + lazy val lazysym = 'lazySymbol + lazy val another = 'another + lazy val lastone = 'lastone +} + +/* + * Tests symbols to see if they work correct. + */ +object Test { + class Inner { + val simba = 'smba + var mfs: Symbol = null + mfs = Symbol("mfsa") + } + + object InnerObject { + val o1 = 'aaa + val o2 = 'ddd + } + + def aSymbol = 'myFirstSymbol + val anotherSymbol = 'mySecondSymbol + + def main(args: Array[String]) { + testLiterals + testForLoop + testInnerClasses + testInnerObjects + testWithHashMaps + testLists + testAnonymous + testNestedObject + testInheritance + testTraits + testLazyTraits + testLazyObjects + } + + def testLiterals { + val scl = new Slazz + assert(scl.s1 == aSymbol) + assert(scl.s2 == anotherSymbol) + assert(scl.s3 == 'myThirdSymbol) + assert(scl.s4 == Symbol.apply("myFourthSymbol")) + assert(scl.s1 == Symbol("myFirstSymbol")) + } + + def testForLoop { + for (i <- 0 until 100) List("Val" + i) + } + + def testInnerClasses { + val innerPower = new Inner + assert(innerPower.simba == 'smba) + assert(innerPower.mfs == 'mfsa) + } + + def testInnerObjects { + assert(InnerObject.o1 == 'aaa) + assert(InnerObject.o2 == 'ddd) + } + + def testWithHashMaps { + val map = new collection.mutable.HashMap[Symbol, Symbol] + map.put(InnerObject.o1, 'smba) + map.put(InnerObject.o2, 'mfsa) + map.put(Symbol("WeirdKey" + 1), Symbol("Weird" + "Val" + 1)) + assert(map('aaa) == 'smba) + assert(map('ddd) == 'mfsa) + assert(map('WeirdKey1) == Symbol("WeirdVal1")) + + map.clear + for (i <- 0 until 100) map.put(Symbol("symKey" + i), Symbol("symVal" + i)) + assert(map(Symbol("symKey15")) == Symbol("symVal15")) + assert(map('symKey22) == 'symVal22) + assert(map('symKey73) == 'symVal73) + assert(map('symKey56) == 'symVal56) + assert(map('symKey91) == 'symVal91) + } + + def testLists { + var lst: List[Symbol] = Nil + for (i <- 0 until 100) lst ::= Symbol("lsym" + (99 - i)) + assert(lst(0) == 'lsym0) + assert(lst(10) == 'lsym10) + assert(lst(30) == 'lsym30) + assert(lst(40) == 'lsym40) + assert(lst(65) == 'lsym65) + assert(lst(90) == 'lsym90) + } + + def testAnonymous { + val anon = () => { + val simba = 'smba + simba + } + val inner = new Inner + assert(anon() == inner.simba) + assert(anon().toString == "'smba") + } + + def testNestedObject { + object nested { + def sign = 'sign + def insignia = 'insignia + } + assert(nested.sign == 'sign) + assert(nested.insignia == 'insignia) + assert(('insignia).toString == "'insignia") + } + + def testInheritance { + val base = new Base + val sub = new Sub + assert(base.basesymbol == 'symbase) + assert(sub.subsymbol == 'symsub) + assert(sub.basesymbol == 'symbase) + + val anon = new Sub { + def subsubsymbol = 'symsubsub + } + assert(anon.subsubsymbol == 'symsubsub) + assert(anon.subsymbol == 'symsub) + assert(anon.basesymbol == 'symbase) + + object nested extends Sub { + def objsymbol = 'symobj + } + assert(nested.objsymbol == 'symobj) + assert(nested.subsymbol == 'symsub) + assert(nested.basesymbol == 'symbase) + assert(('symbase).toString == "'symbase") + } + + def testTraits { + val fromTrait = new AnyRef with Signs { + def traitsymbol = 'traitSymbol + } + + assert(fromTrait.traitsymbol == 'traitSymbol) + assert(fromTrait.ind == 'indication) + assert(fromTrait.trace == 'trace) + assert(('trace).toString == "'trace") + + trait Compl { + val s1 = 's1 + def s2 = 's2 + object inner { + val s3 = 's3 + val s4 = 's4 + } + } + + val compl = new Sub with Signs with Compl + assert(compl.s1 == 's1) + assert(compl.s2 == 's2) + assert(compl.inner.s3 == 's3) + assert(compl.inner.s4 == 's4) + assert(compl.ind == 'indication) + assert(compl.trace == 'trace) + assert(compl.subsymbol == 'symsub) + assert(compl.basesymbol == 'symbase) + + object Local extends Signs with Compl { + val s5 = 's5 + def s6 = 's6 + object inner2 { + val s7 = 's7 + def s8 = 's8 + } + } + assert(Local.s5 == 's5) + assert(Local.s6 == 's6) + assert(Local.inner2.s7 == 's7) + assert(Local.inner2.s8 == 's8) + assert(Local.inner.s3 == 's3) + assert(Local.inner.s4 == 's4) + assert(Local.s1 == 's1) + assert(Local.s2 == 's2) + assert(Local.trace == 'trace) + assert(Local.ind == 'indication) + assert(('s8).toString == "'s8") + } + + def testLazyTraits { + val l1 = new AnyRef with Lazy1 + val l2 = new AnyRef with Lazy2 + val l3 = new AnyRef with Lazy3 + + l1.v1 + l2.v2 + l3.v3 + assert((l1.s1).toString == "'lazySymbol1") + assert(l2.s2 == Symbol("lazySymbol" + 2)) + assert(l3.s3 == 'lazySymbol3) + } + + def testLazyObjects { + assert(SingletonOfLazyness.lazysym == 'lazySymbol) + assert(SingletonOfLazyness.another == Symbol("ano" + "ther")) + assert((SingletonOfLazyness.lastone).toString == "'lastone") + + object nested { + lazy val sym1 = 'snested1 + lazy val sym2 = 'snested2 + } + + assert(nested.sym1 == 'snested1) + assert(nested.sym2 == Symbol("snested" + "2")) + } + +} + + + + + + + + + + + + diff --git a/test/files/run/priorityQueue.scala b/test/files/run/priorityQueue.scala index f695b41a37..e582448342 100644 --- a/test/files/run/priorityQueue.scala +++ b/test/files/run/priorityQueue.scala @@ -251,6 +251,9 @@ object Test { //println(pq) //assert(ind == 5) //assertPriorityDestructive(pq) + + //pq.clear + //pq ++= (0 until 10) } } |