From c6a783ac089d8cf5a60a98946af5e80aff5a7d32 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 4 Feb 2012 14:36:14 -0800 Subject: Making AnyVal into a class instead of a trait. -- traits can extend Any, AnyRef, or AnyVal -- classes can extend AnyRef or AnyVal but not Any. This breaks reflection for the moment as it smuggles AnyVal so far downstream that it's reflecting its way into bytecode (or something) but the following test case goes five for six as anticipated. trait Foo1 extends Any trait Foo2 extends AnyVal trait Foo3 extends AnyRef class Bar1 extends Any // fail @inline class Bar2 extends AnyVal class Bar3 extends AnyRef Eliminated various hijinx from definitions. --- lib/scala-compiler.jar.desired.sha1 | 2 +- lib/scala-library-src.jar.desired.sha1 | 2 +- lib/scala-library.jar.desired.sha1 | 2 +- .../scala/reflect/internal/Definitions.scala | 29 +++++----------------- .../scala/tools/nsc/ast/parser/Parsers.scala | 11 ++++---- .../scala/tools/nsc/transform/AddInterfaces.scala | 12 ++++++--- .../scala/tools/nsc/transform/Constructors.scala | 13 ++++++---- .../scala/tools/nsc/typechecker/Typers.scala | 2 ++ src/library/scala/AnyVal.scala | 2 +- test/files/neg/anyval-anyref-parent.check | 4 +++ test/files/neg/anyval-anyref-parent.scala | 7 ++++++ 11 files changed, 45 insertions(+), 41 deletions(-) create mode 100644 test/files/neg/anyval-anyref-parent.check create mode 100644 test/files/neg/anyval-anyref-parent.scala diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1 index 22e714ad41..79f6de5e27 100644 --- a/lib/scala-compiler.jar.desired.sha1 +++ b/lib/scala-compiler.jar.desired.sha1 @@ -1 +1 @@ -83df84e719c0f966c67855a1b453aaff2c01e4f7 ?scala-compiler.jar +40f87533e0d03ad04ca632119286d347ee54d8ae ?scala-compiler.jar diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1 index cb39ee8604..cfb865f1e8 100644 --- a/lib/scala-library-src.jar.desired.sha1 +++ b/lib/scala-library-src.jar.desired.sha1 @@ -1 +1 @@ -04d9d47973b10ec7353e2a8199b1bd5c62fb540a ?scala-library-src.jar +4a34794dd9a45cd2e8603de559f565535e7aa74b ?scala-library-src.jar diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1 index 009d5f82ea..28a2c586a0 100644 --- a/lib/scala-library.jar.desired.sha1 +++ b/lib/scala-library.jar.desired.sha1 @@ -1 +1 @@ -c8e01ec6416bd883e996cf8c6916bf0173c31486 ?scala-library.jar +3516dc2e17bf72b1e4bc665e59f6b7ec51cba48d ?scala-library.jar diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 82d7f947e6..7bd0c0f919 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -230,17 +230,12 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val AnyCompanionClass = getRequiredClass("scala.AnyCompanion") initFlags (SEALED | ABSTRACT | TRAIT) lazy val AnyValCompanionClass = getRequiredClass("scala.AnyValCompanion") initFlags (SEALED | ABSTRACT | TRAIT) - private var oldValueScheme = true - - lazy val AnyValClass = ScalaPackageClass.info member tpnme.AnyVal -// lazy val AnyValClass = ScalaPackageClass.info member tpnme.AnyVal orElse { -// // println("new anyval") -// oldValueScheme = true -// val anyval = enterNewClass(ScalaPackageClass, tpnme.AnyVal, anyparam, 0L) -// val av_constr = anyval.newClassConstructor(NoPosition) -// anyval.info.decls enter av_constr -// anyval -// } + lazy val AnyValClass = ScalaPackageClass.info member tpnme.AnyVal orElse { + val anyval = enterNewClass(ScalaPackageClass, tpnme.AnyVal, List(AnyClass.tpe, NotNullClass.tpe), 0L) + val av_constr = anyval.newClassConstructor(NoPosition) + anyval.info.decls enter av_constr + anyval + } lazy val AnyVal_getClass = enterNewMethod(AnyValClass, nme.getClass_, Nil, getClassReturnType(AnyValClass.tpe)) // bottom types @@ -1077,22 +1072,10 @@ trait Definitions extends reflect.api.StandardDefinitions { Object_synchronized, Object_isInstanceOf, Object_asInstanceOf, - //AnyVal_getClass, String_+, ComparableClass ) - /* Removing the anyref parent they acquire from having a source file. - */ - if (oldValueScheme) { - setParents(AnyValClass, List(NotNullClass.tpe, AnyClass.tpe)) - } else { - AnyVal_getClass // force it! - } - ScalaValueClasses foreach { sym => - setParents(sym, anyvalparam) - } - isInitialized = true } //init diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 8e5a0139a5..f7401c813a 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -2753,7 +2753,11 @@ self => val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart atPos(tstart0) { - if (isPrimitiveType(name)) + if (inScalaPackage && name == tpnme.AnyVal) { + val constructor = DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(), Block(Nil, Literal(Constant()))) + Template(parents0, self, constructor :: body) + } + else if (isPrimitiveType(name)) Template(List(scalaAnyValConstr), self, body) else if (parents0 exists isReferenceToAnyVal) { // @inline and other restrictions enforced in refchecks @@ -2761,10 +2765,7 @@ self => } else { val parents = ( - if (parents0.isEmpty) { - if (inScalaPackage && name == tpnme.AnyVal) List(scalaAnyConstr) - else List(scalaAnyRefConstr) - } + if (parents0.isEmpty) List(scalaAnyRefConstr) /*if (!isInterface(mods, body) && !isScalaArray(name)) parents0 /* :+ scalaScalaObjectConstr*/ else*/ diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 89dfbfd317..8fe82258e2 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -301,12 +301,16 @@ abstract class AddInterfaces extends InfoTransform { if mc.hasFlag(lateINTERFACE)) yield mixinConstructorCall(implClass(mc)) } - (tree: @unchecked) match { + tree match { case Block(stats, expr) => // needs `hasSymbol` check because `supercall` could be a block (named / default args) - val (presuper, supercall :: rest) = stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER)) - // assert(supercall.symbol.isClassConstructor, supercall) - treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr) + stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER)) match { + case (presuper, supercall :: rest) => + stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER)) + treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr) + case (Nil, Nil) => // AnyVal constructor + Literal(Constant()) + } } } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 256f13b3fb..a672059211 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -44,11 +44,14 @@ abstract class Constructors extends Transform with ast.TreeDSL { ) // decompose primary constructor into the three entities above. val constrInfo: ConstrInfo = { - val primary = stats find (_.symbol.isPrimaryConstructor) - assert(primary.isDefined, "no constructor in template: impl = " + impl) - - val ddef @ DefDef(_, _, _, List(vparams), _, rhs @ Block(_, _)) = primary.get - ConstrInfo(ddef, vparams map (_.symbol), rhs) + stats find (_.symbol.isPrimaryConstructor) match { + case Some(ddef @ DefDef(_, _, _, List(vparams), _, rhs @ Block(_, _))) => + ConstrInfo(ddef, vparams map (_.symbol), rhs) + case x => + // assert(false, "no constructor in template: impl = " + impl) + // AnyVal constructor + return impl + } } import constrInfo._ diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 1d84f7fdaf..ba3172dd06 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1610,6 +1610,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { * @param rhs ... */ def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree) { + if (clazz eq AnyValClass) + return debuglog("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs)//debug def decompose(call: Tree): (Tree, List[Tree]) = call match { case Apply(fn, args) => diff --git a/src/library/scala/AnyVal.scala b/src/library/scala/AnyVal.scala index daad6f6f5e..393f0899f4 100644 --- a/src/library/scala/AnyVal.scala +++ b/src/library/scala/AnyVal.scala @@ -25,7 +25,7 @@ package scala * The ''integer types'' include the subrange types as well as [[scala.Int]] and [[scala.Long]]. * The ''floating point types'' are [[scala.Float]] and [[scala.Double]]. */ -trait AnyVal extends Any with NotNull { +abstract class AnyVal extends Any with NotNull { // disabled for now to make the standard build go through. // Once we have a new strap we can uncomment this and delete the AnyVal_getClass entry in Definitions. def getClass(): Class[_ <: AnyVal] = ??? diff --git a/test/files/neg/anyval-anyref-parent.check b/test/files/neg/anyval-anyref-parent.check new file mode 100644 index 0000000000..b40a0f2710 --- /dev/null +++ b/test/files/neg/anyval-anyref-parent.check @@ -0,0 +1,4 @@ +anyval-anyref-parent.scala:5: error: Any does not have a constructor +class Bar1 extends Any // fail + ^ +one error found diff --git a/test/files/neg/anyval-anyref-parent.scala b/test/files/neg/anyval-anyref-parent.scala new file mode 100644 index 0000000000..b7bb122ea8 --- /dev/null +++ b/test/files/neg/anyval-anyref-parent.scala @@ -0,0 +1,7 @@ +trait Foo1 extends Any +trait Foo2 extends AnyVal +trait Foo3 extends AnyRef + +class Bar1 extends Any // fail +@inline class Bar2 extends AnyVal +class Bar3 extends AnyRef -- cgit v1.2.3