From e61eff23df977eeed19bfe253b01b69cce47dfa3 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 27 Jan 2012 16:30:01 -0800 Subject: Unsealed AnyVal. Hacks here and there to allow them to survive at least to erasure. Since nothing is done with them there yet, they inevitably crash and burn a little ways beyond that. --- src/compiler/scala/reflect/internal/TreeInfo.scala | 11 +---------- .../scala/reflect/internal/TreePrinters.scala | 23 +++++++++++++--------- src/compiler/scala/reflect/internal/Trees.scala | 12 +++++++++++ src/compiler/scala/tools/cmd/gen/AnyVals.scala | 6 +++--- .../scala/tools/nsc/ast/parser/Parsers.scala | 20 ++++++++++++------- .../tools/nsc/interpreter/MemberHandlers.scala | 2 +- .../tools/nsc/typechecker/ContextErrors.scala | 2 +- .../scala/tools/nsc/typechecker/RefChecks.scala | 10 ++++++---- .../scala/tools/nsc/typechecker/Typers.scala | 10 +++------- 9 files changed, 54 insertions(+), 42 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala index e3ee39d2a0..4380487555 100644 --- a/src/compiler/scala/reflect/internal/TreeInfo.scala +++ b/src/compiler/scala/reflect/internal/TreeInfo.scala @@ -440,15 +440,6 @@ abstract class TreeInfo { EmptyTree } - /** Is the tree Predef, scala.Predef, or _root_.scala.Predef? - */ - def isPredefExpr(t: Tree) = t match { - case Ident(nme.Predef) => true - case Select(Ident(nme.scala_), nme.Predef) => true - case Select(Select(Ident(nme.ROOTPKG), nme.scala_), nme.Predef) => true - case _ => false - } - /** Does list of trees start with a definition of * a class of module with given name (ignoring imports) */ @@ -468,7 +459,7 @@ abstract class TreeInfo { // Top-level definition whose leading imports include Predef. def containsLeadingPredefImport(defs: List[Tree]): Boolean = defs match { case PackageDef(_, defs1) :: _ => containsLeadingPredefImport(defs1) - case Import(expr, _) :: rest => isPredefExpr(expr) || containsLeadingPredefImport(rest) + case Import(expr, _) :: rest => isReferenceToPredef(expr) || containsLeadingPredefImport(rest) case _ => false } diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala index 3a0717d344..00c20535ba 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/compiler/scala/reflect/internal/TreePrinters.scala @@ -235,16 +235,21 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => case Template(parents, self, body) => val currentOwner1 = currentOwner if (tree.symbol != NoSymbol) currentOwner = tree.symbol.owner - printRow(parents, " with ") - if (!body.isEmpty) { - if (self.name != nme.WILDCARD) { - print(" { ", self.name); printOpt(": ", self.tpt); print(" => ") - } else if (!self.tpt.isEmpty) { - print(" { _ : ", self.tpt, " => ") - } else { - print(" {") + if (parents exists isReferenceToAnyVal) { + print("AnyVal") + } + else { + printRow(parents, " with ") + if (!body.isEmpty) { + if (self.name != nme.WILDCARD) { + print(" { ", self.name); printOpt(": ", self.tpt); print(" => ") + } else if (!self.tpt.isEmpty) { + print(" { _ : ", self.tpt, " => ") + } else { + print(" {") + } + printColumn(body, "", ";", "}") } - printColumn(body, "", ";", "}") } currentOwner = currentOwner1 diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 5bb0c98bfb..7ce087df2f 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -10,6 +10,18 @@ import Flags._ import api.Modifier trait Trees extends api.Trees { self: SymbolTable => + + // Belongs in TreeInfo but then I can't reach it from TreePrinters. + def isReferenceToScalaMember(t: Tree, Id: Name) = t match { + case Ident(Id) => true + case Select(Ident(nme.scala_), Id) => true + case Select(Select(Ident(nme.ROOTPKG), nme.scala_), Id) => true + case _ => false + } + /** Is the tree Predef, scala.Predef, or _root_.scala.Predef? + */ + def isReferenceToPredef(t: Tree) = isReferenceToScalaMember(t, nme.Predef) + def isReferenceToAnyVal(t: Tree) = isReferenceToScalaMember(t, tpnme.AnyVal) // --- modifiers implementation --------------------------------------- diff --git a/src/compiler/scala/tools/cmd/gen/AnyVals.scala b/src/compiler/scala/tools/cmd/gen/AnyVals.scala index 8f82c997db..ab4a4a4402 100644 --- a/src/compiler/scala/tools/cmd/gen/AnyVals.scala +++ b/src/compiler/scala/tools/cmd/gen/AnyVals.scala @@ -182,7 +182,7 @@ trait AnyValReps { def classLines: List[String] def objectLines: List[String] def commonClassLines = List( - "def getClass(): Class[@name@]" + "override def getClass(): Class[@name@]" ) def lcname = name.toLowerCase @@ -429,7 +429,7 @@ def &(x: Boolean): Boolean = sys.error("stub") */ def ^(x: Boolean): Boolean = sys.error("stub") -def getClass(): Class[Boolean] = sys.error("stub") +override def getClass(): Class[Boolean] = sys.error("stub") """.trim.lines.toList def objectLines = interpolate(allCompanions).lines.toList @@ -443,7 +443,7 @@ def getClass(): Class[Boolean] = sys.error("stub") */ """ def classLines = List( - """def getClass(): Class[Unit] = sys.error("stub")""" + """override def getClass(): Class[Unit] = sys.error("stub")""" ) def objectLines = interpolate(allCompanions).lines.toList diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index fe6dcc9138..c3e156104f 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -290,11 +290,11 @@ self => inScalaPackage = false currentPackage = "" } - private lazy val anyValNames: Set[Name] = tpnme.ScalaValueNames.toSet + tpnme.AnyVal + private lazy val primitiveNames: Set[Name] = tpnme.ScalaValueNames.toSet - private def inScalaRootPackage = inScalaPackage && currentPackage == "scala" - private def isScalaArray(name: Name) = inScalaRootPackage && name == tpnme.Array - private def isAnyValType(name: Name) = inScalaRootPackage && anyValNames(name) + private def inScalaRootPackage = inScalaPackage && currentPackage == "scala" + private def isScalaArray(name: Name) = inScalaRootPackage && name == tpnme.Array + private def isPrimitiveType(name: Name) = inScalaRootPackage && primitiveNames(name) def parseStartRule: () => Tree @@ -2753,9 +2753,15 @@ self => val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart atPos(tstart0) { - if (isAnyValType(name)) { - val parent = if (name == tpnme.AnyVal) tpnme.Any else tpnme.AnyVal - Template(List(scalaDot(parent)), self, body) + if (isPrimitiveType(name)) { + Template(List(scalaDot(tpnme.AnyVal)), self, body) + } + else if (parents0 exists isReferenceToAnyVal) { + // TODO - enforce @inline annotation, and no other parents + Template(parents0, self, body) + } + else if (name == tpnme.AnyVal) { + Template(List(scalaDot(tpnme.Any)), self, body) } else { val parents = ( diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index c742ab89c0..37dd032135 100644 --- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -182,7 +182,7 @@ trait MemberHandlers { // TODO: Need to track these specially to honor Predef masking attempts, // because they must be the leading imports in the code generated for each // line. We can use the same machinery as Contexts now, anyway. - def isPredefImport = treeInfo.isPredefExpr(expr) + def isPredefImport = isReferenceToPredef(expr) // wildcard imports, e.g. import foo._ private def selectorWild = selectors filter (_.name == nme.USCOREkw) diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 6ee09d064f..ed18e2ead5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -534,7 +534,7 @@ trait ContextErrors { NormalTypeError(parent, "illegal inheritance from final "+mixin) def ParentSealedInheritanceError(parent: Tree, psym: Symbol) = - NormalTypeError(parent, "illegal inheritance from sealed " + psym + ": " + context.unit.source.file.canonicalPath + " != " + psym.sourceFile.canonicalPath) + NormalTypeError(parent, "illegal inheritance from sealed " + psym)// + ": " + context.unit.source.file.canonicalPath + " != " + psym.sourceFile.canonicalPath) def ParentSelfTypeConformanceError(parent: Tree, selfType: Type) = NormalTypeError(parent, diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index a99d09173e..d492ba3662 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -685,10 +685,12 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R unit.error(clazz.pos, abstractErrorMessage) } else if (clazz.isTrait) { // prevent abstract methods in interfaces that override final members in Object; see #4431 - for (decl <- clazz.info.decls.iterator) { - val overridden = decl.overriddenSymbol(ObjectClass) - if (overridden.isFinal) - unit.error(decl.pos, "trait cannot redefine final method from class AnyRef") + if (!(clazz isSubClass AnyValClass)) { + for (decl <- clazz.info.decls.iterator) { + val overridden = decl.overriddenSymbol(ObjectClass) + if (overridden.isFinal) + unit.error(decl.pos, "trait cannot redefine final method from class AnyRef") + } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 770b55d6ab..f2aa1fcae4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1336,13 +1336,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (psym.isFinal) pending += ParentFinalInheritanceError(parent, psym) - if (psym.isSealed && !phase.erasedTypes) { - // AnyVal is sealed, but we have to let the value classes through manually - if (context.unit.source.file == psym.sourceFile || isValueClass(context.owner)) - psym addChild context.owner - else - pending += ParentSealedInheritanceError(parent, psym) - } + if (psym.isSealed && !phase.erasedTypes) + pending += ParentSealedInheritanceError(parent, psym) + if (!(selfType <:< parent.tpe.typeOfThis) && !phase.erasedTypes && !context.owner.isSynthetic && // don't check synthetic concrete classes for virtuals (part of DEVIRTUALIZE) -- cgit v1.2.3