From 6b8aed72e4f7a7135a434533399a772bf7078101 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 4 Feb 2012 11:23:16 -0800 Subject: Made Any parents work more. Working on type printing logic. --- .../scala/reflect/internal/Definitions.scala | 42 +++++++++++++++---- src/compiler/scala/reflect/internal/Types.scala | 49 ++++++++++++---------- .../scala/reflect/internal/transform/Erasure.scala | 8 +--- .../scala/tools/nsc/ast/parser/Parsers.scala | 13 +++--- .../scala/tools/nsc/ast/parser/TreeBuilder.scala | 10 +++-- .../scala/tools/nsc/transform/Erasure.scala | 2 +- .../tools/nsc/typechecker/NamesDefaults.scala | 2 +- .../scala/tools/nsc/typechecker/Typers.scala | 22 +++++----- src/library/scala/AnyVal.scala | 8 ++-- src/library/scala/NotNull.scala | 2 +- 10 files changed, 91 insertions(+), 67 deletions(-) diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 47c711e81c..82d7f947e6 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -232,14 +232,15 @@ trait Definitions extends reflect.api.StandardDefinitions { private var oldValueScheme = true - 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 +// 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 AnyVal_getClass = enterNewMethod(AnyValClass, nme.getClass_, Nil, getClassReturnType(AnyValClass.tpe)) // bottom types @@ -722,6 +723,31 @@ trait Definitions extends reflect.api.StandardDefinitions { } } + /** Remove references to class Object (other than the head) in a list of parents */ + def removeLaterObjects(tps: List[Type]): List[Type] = tps match { + case Nil => Nil + case x :: xs => x :: xs.filter(_.typeSymbol != ObjectClass) + } + /** Order a list of types with non-trait classes before others. */ + def classesFirst(tps: List[Type]): List[Type] = { + val (classes, others) = tps partition (t => t.typeSymbol.isClass && !t.typeSymbol.isTrait) + if (classes.isEmpty || others.isEmpty || (tps startsWith classes)) tps + else classes ::: others + } + /** The following transformations applied to a list of parents. + * If any parent is a class/trait, all parents which are Object + * or an alias of it are discarded. Otherwise, all Objects other + * the head of the list are discarded. + */ + def normalizedParents(parents: List[Type]): List[Type] = { + if (parents exists (t => (t.typeSymbol ne ObjectClass) && t.typeSymbol.isClass)) + parents filterNot (_.typeSymbol eq ObjectClass) + else + removeLaterObjects(parents) + } + def parentsString(parents: List[Type]) = + normalizedParents(parents) mkString " with " + // members of class java.lang.{ Object, String } lazy val Object_## = enterNewMethod(ObjectClass, nme.HASHHASH, Nil, inttype, FINAL) lazy val Object_== = enterNewMethod(ObjectClass, nme.EQ, anyrefparam, booltype, FINAL) diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 3ed6544613..89664bad9f 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -410,6 +410,11 @@ trait Types extends api.Types { self: SymbolTable => * inherited by typerefs, singleton types, and refinement types, * The empty list for all other types */ def parents: List[Type] = List() + + /** For a class with nonEmpty parents, the first parent. + * Otherwise some specific fixed top type. + */ + def firstParent = if (parents.nonEmpty) parents.head else ObjectClass.tpe /** For a typeref or single-type, the prefix of the normalized type (@see normalize). * NoType for all other types. */ @@ -1412,10 +1417,10 @@ trait Types extends api.Types { self: SymbolTable => // override def isNullable: Boolean = // parents forall (p => p.isNullable && !p.typeSymbol.isAbstractType); - override def safeToString: String = - parents.mkString(" with ") + + override def safeToString: String = parentsString(parents) + ( (if (settings.debug.value || parents.isEmpty || (decls.elems ne null)) decls.mkString("{", "; ", "}") else "") + ) } protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = { @@ -1477,7 +1482,7 @@ trait Types extends api.Types { self: SymbolTable => else { //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG // optimized, since this seems to be performance critical - val superclazz = tpe.parents.head + val superclazz = tpe.firstParent var mixins = tpe.parents.tail val sbcs = superclazz.baseClasses var bcs = sbcs @@ -1524,7 +1529,7 @@ trait Types extends api.Types { self: SymbolTable => ) override def typeParams = - if (isHigherKinded) parents.head.typeParams + if (isHigherKinded) firstParent.typeParams else super.typeParams //@M may result in an invalid type (references to higher-order args become dangling ) @@ -2142,12 +2147,12 @@ trait Types extends api.Types { self: SymbolTable => ) else "" ) + private def finishPrefix(rest: String) = ( if (sym.isPackageClass) packagePrefix + rest else if (sym.isModuleClass) objectPrefix + rest else if (!sym.isInitialized) rest - else if (sym.isAnonymousClass && !phase.erasedTypes) - thisInfo.parents.mkString("", " with ", refinementString) + else if (sym.isAnonymousClass && !phase.erasedTypes) parentsString(thisInfo.parents) + refinementString else if (sym.isRefinementClass) "" + thisInfo else rest ) @@ -3225,11 +3230,21 @@ trait Types extends api.Types { self: SymbolTable => * comment or in the code? */ def intersectionType(tps: List[Type], owner: Symbol): Type = tps match { - case List(tp) => - tp - case _ => - refinedType(tps, owner) -/* + case tp :: Nil => tp + case _ => refinedType(tps, owner) + } + /** A creator for intersection type where intersections of a single type are + * replaced by the type itself. + */ + def intersectionType(tps: List[Type]): Type = tps match { + case tp :: Nil => tp + case _ => refinedType(tps, commonOwner(tps)) + } + +/**** This implementation to merge parents was checked in in commented-out + form and has languished unaltered for five years. I think we should + use it or lose it. + def merge(tps: List[Type]): List[Type] = tps match { case tp :: tps1 => val tps1a = tps1 filter (_.typeSymbol.==(tp.typeSymbol)) @@ -3244,14 +3259,6 @@ trait Types extends api.Types { self: SymbolTable => } refinedType(merge(tps), owner) */ - } - - /** A creator for intersection type where intersections of a single type are - * replaced by the type itself. */ - def intersectionType(tps: List[Type]): Type = tps match { - case List(tp) => tp - case _ => refinedType(tps, commonOwner(tps)) - } /** A creator for type applications */ def appliedType(tycon: Type, args: List[Type]): Type = @@ -4504,9 +4511,7 @@ trait Types extends api.Types { self: SymbolTable => else { commonOwnerMap.clear() tps foreach (commonOwnerMap traverse _) - val result = if (commonOwnerMap.result ne null) commonOwnerMap.result else NoSymbol - debuglog(tps.mkString("commonOwner(", ", ", ") == " + result)) - result + if (commonOwnerMap.result ne null) commonOwnerMap.result else NoSymbol } } diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala index 4775541855..7c360e1f25 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala @@ -225,13 +225,7 @@ trait Erasure { /** Type reference after erasure */ def erasedTypeRef(sym: Symbol): Type = - typeRef(erasure(sym, sym.owner.tpe), sym, List()) - - /** Remove duplicate references to class Object in a list of parent classes */ - private def removeLaterObjects(tps: List[Type]): List[Type] = tps match { - case tp :: rest => tp :: (rest filter (_.typeSymbol != ObjectClass)) - case _ => tps - } + typeRef(erasure(sym, sym.owner.tpe), sym, Nil) /** The symbol's erased info. This is the type's erasure, except for the following symbols: * diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 40e7d88a3b..8e5a0139a5 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -2753,19 +2753,18 @@ self => val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart atPos(tstart0) { - if (isPrimitiveType(name)) { - Template(List(scalaDot(tpnme.AnyVal)), self, body) - } + if (isPrimitiveType(name)) + Template(List(scalaAnyValConstr), self, body) else if (parents0 exists isReferenceToAnyVal) { // @inline and other restrictions enforced in refchecks Template(parents0, self, body) } - else if (name == tpnme.AnyVal) { - Template(List(scalaDot(tpnme.Any)), self, body) - } else { val parents = ( - if (parents0.isEmpty) List(scalaAnyRefConstr) + if (parents0.isEmpty) { + if (inScalaPackage && name == tpnme.AnyVal) List(scalaAnyConstr) + else List(scalaAnyRefConstr) + } /*if (!isInterface(mods, body) && !isScalaArray(name)) parents0 /* :+ scalaScalaObjectConstr*/ else*/ diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 906932f591..40389466e2 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -29,11 +29,13 @@ abstract class TreeBuilder { def rootId(name: Name) = gen.rootId(name) def rootScalaDot(name: Name) = gen.rootScalaDot(name) def scalaDot(name: Name) = gen.scalaDot(name) - def scalaAnyRefConstr = gen.scalaAnyRefConstr - def scalaUnitConstr = gen.scalaUnitConstr - def productConstr = gen.productConstr + def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) + def scalaAnyValConstr = scalaDot(tpnme.AnyVal) + def scalaAnyConstr = scalaDot(tpnme.Any) + def scalaUnitConstr = scalaDot(tpnme.Unit) + def productConstr = scalaDot(tpnme.Product) def productConstrN(n: Int) = scalaDot(newTypeName("Product" + n)) - def serializableConstr = gen.serializableConstr + def serializableConstr = scalaDot(tpnme.Serializable) def convertToTypeName(t: Tree) = gen.convertToTypeName(t) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 30bfdbaf5b..efbfe4da41 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -714,7 +714,7 @@ abstract class Erasure extends AddInterfaces var bridges: List[Tree] = List() val opc = atPhase(currentRun.explicitouterPhase) { new overridingPairs.Cursor(owner) { - override def parents: List[Type] = List(owner.info.parents.head) + override def parents: List[Type] = List(owner.info.firstParent) override def exclude(sym: Symbol): Boolean = !sym.isMethod || sym.isPrivate || super.exclude(sym) } diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 3a3c244d1c..359e72e3e4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -228,7 +228,7 @@ trait NamesDefaults { self: Analyzer => case Select(sp @ Super(_, _), _) if isConstr => // 'moduleQual' fixes #3207. selection of the companion module of the // superclass needs to have the same prefix as the superclass. - blockWithoutQualifier(moduleQual(baseFun.pos, sp.symbol.tpe.parents.head)) + blockWithoutQualifier(moduleQual(baseFun.pos, sp.symbol.tpe.firstParent)) // self constructor calls (in secondary constructors) case Select(tp, name) if isConstr => diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index a20e78a81f..fdeab7b565 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1208,7 +1208,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val supertpt1 = typedType(supertpt) if (!supertpt1.isErrorTyped) { mixins = supertpt1 :: mixins - supertpt = TypeTree(supertpt1.tpe.parents.head) setPos supertpt.pos.focus + supertpt = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus } } if (supertpt.tpe.typeSymbol == AnyClass && firstParent.isTrait && firstParent != AnyValClass) @@ -1302,12 +1302,15 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { else xs ) } + fixDuplicates(supertpt :: mixins) mapConserve (tpt => checkNoEscaping.privates(clazz, tpt)) } catch { case ex: TypeError => // fallback in case of cyclic errors // @H none of the tests enter here but I couldn't rule it out + log("Type error calculating parents in template " + templ) + log("Error: " + ex) ParentTypesError(templ, ex) List(TypeTree(AnyRefClass.tpe)) } @@ -1415,7 +1418,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { _.typedTemplate(cdef.impl, parentTypes(cdef.impl)) } val impl2 = finishMethodSynthesis(impl1, clazz, context) - if (clazz.isTrait && clazz.info.parents.nonEmpty && clazz.info.parents.head.typeSymbol == AnyClass) + if (clazz.isTrait && clazz.info.parents.nonEmpty && clazz.info.firstParent.typeSymbol == AnyClass) for (stat <- impl2.body) if (!treeInfo.isAllowedInAnyTrait(stat)) unit.error(stat.pos, "this statement is not allowed in trait extending from class Any: "+stat) @@ -3670,16 +3673,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - val owntype = - if (mix.isEmpty) { - if ((mode & SUPERCONSTRmode) != 0) - if (clazz.info.parents.isEmpty) AnyRefClass.tpe // can happen due to cyclic references ==> #1036 - else clazz.info.parents.head - else intersectionType(clazz.info.parents) - } else { - findMixinSuper(clazz.tpe) - } - + val owntype = ( + if (!mix.isEmpty) findMixinSuper(clazz.tpe) + else if ((mode & SUPERCONSTRmode) != 0) clazz.info.firstParent + else intersectionType(clazz.info.parents) + ) treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype) } diff --git a/src/library/scala/AnyVal.scala b/src/library/scala/AnyVal.scala index ed32fb7302..daad6f6f5e 100644 --- a/src/library/scala/AnyVal.scala +++ b/src/library/scala/AnyVal.scala @@ -25,8 +25,8 @@ 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 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] = ??? +trait 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/src/library/scala/NotNull.scala b/src/library/scala/NotNull.scala index f90b95c789..64f999a932 100644 --- a/src/library/scala/NotNull.scala +++ b/src/library/scala/NotNull.scala @@ -12,4 +12,4 @@ package scala * A marker trait for things that are not allowed to be null * @since 2.5 */ -trait NotNull {} +trait NotNull extends Any {} -- cgit v1.2.3