diff options
9 files changed, 55 insertions, 48 deletions
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index d3641c1ee8..767f71a7c6 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -499,12 +499,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR) - final def isInlineClass = + final def isDerivedValueClass = isClass && info.parents.headOption.getOrElse(AnyClass.tpe).typeSymbol == AnyValClass && !isPrimitiveValueClass final def isMethodWithExtension = - isMethod && owner.isInlineClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR) + isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR) final def isAnonymousClass = isClass && (name containsName tpnme.ANON_CLASS_NAME) final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME) diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index a93f8ea683..15918cc013 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -65,8 +65,8 @@ import util.Statistics._ // inst is the instantiation and constr is a list of bounds. case DeBruijnIndex(level, index) // for dependent method types: a type referring to a method parameter. - case ErasedInlineType(tp) - // only used during erasure of inline classes. + case ErasedValueType(tp) + // only used during erasure of derived value classes. */ trait Types extends api.Types { self: SymbolTable => @@ -3076,15 +3076,15 @@ trait Types extends api.Types { self: SymbolTable => } } - abstract case class ErasedInlineType(sym: Symbol) extends Type { + abstract case class ErasedValueType(sym: Symbol) extends Type { override def safeToString = sym.name+"$unboxed" } - final class UniqueErasedInlineType(sym: Symbol) extends ErasedInlineType(sym) with UniqueType + final class UniqueErasedValueType(sym: Symbol) extends ErasedValueType(sym) with UniqueType - object ErasedInlineType { + object ErasedValueType { def apply(sym: Symbol): Type = - unique(new UniqueErasedInlineType(sym)) + unique(new UniqueErasedValueType(sym)) } /** A class representing an as-yet unevaluated type. diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala index 2cf171aad3..e87de8db80 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala @@ -74,7 +74,7 @@ trait Erasure { def eraseNormalClassRef(pre: Type, clazz: Symbol): Type = typeRef(apply(rebindInnerClass(pre, clazz)), clazz, List()) // #2585 - protected def eraseInlineClassRef(clazz: Symbol): Type = + protected def eraseDerivedValueClassRef(clazz: Symbol): Type = scalaErasure(underlyingOfValueClass(clazz)) def apply(tp: Type): Type = tp match { @@ -90,7 +90,7 @@ trait Erasure { else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) erasedTypeRef(ObjectClass) else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) else if (sym.isRefinementClass) apply(mergeParents(tp.parents)) - else if (sym.isInlineClass) eraseInlineClassRef(sym) + else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(sym) else if (sym.isClass) eraseNormalClassRef(pre, sym) else apply(sym.info) // alias type or abstract type case PolyType(tparams, restpe) => @@ -119,7 +119,7 @@ trait Erasure { } def applyInArray(tp: Type): Type = tp match { - case TypeRef(pre, sym, args) if (sym.isInlineClass) => eraseNormalClassRef(pre, sym) + case TypeRef(pre, sym, args) if (sym.isDerivedValueClass) => eraseNormalClassRef(pre, sym) case _ => apply(tp) } } @@ -159,13 +159,13 @@ trait Erasure { else javaErasure /** This is used as the Scala erasure during the erasure phase itself - * It differs from normal erasure in that value classes are erased to ErasedInlineTypes which + * It differs from normal erasure in that value classes are erased to ErasedValueTypes which * are then later converted to the underlying parameter type in phase posterasure. */ def specialErasure(sym: Symbol)(tp: Type): Type = if (sym != NoSymbol && sym.enclClass.isJavaDefined) erasure(sym)(tp) - else if (sym.isTerm && sym.owner.isInlineClass) + else if (sym.isTerm && sym.owner.isDerivedValueClass) specialErasureAvoiding(sym.owner, tp) else if (sym.isValue && sym.owner.isMethodWithExtension) specialErasureAvoiding(sym.owner.owner, tp) @@ -222,11 +222,11 @@ trait Erasure { object scalaErasure extends ScalaErasureMap /** This is used as the Scala erasure during the erasure phase itself - * It differs from normal erasure in that value classes are erased to ErasedInlineTypes which + * It differs from normal erasure in that value classes are erased to ErasedValueTypes which * are then later converted to the underlying parameter type in phase posterasure. */ object specialScalaErasure extends ScalaErasureMap { - override def eraseInlineClassRef(clazz: Symbol): Type = ErasedInlineType(clazz) + override def eraseDerivedValueClassRef(clazz: Symbol): Type = ErasedValueType(clazz) } object javaErasure extends JavaErasureMap diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 306e00e38d..65b4890c8f 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -387,7 +387,7 @@ abstract class Erasure extends AddInterfaces List(tpt)), List()) if cast.symbol == Object_asInstanceOf && - tpt.tpe.typeSymbol.isInlineClass && + tpt.tpe.typeSymbol.isDerivedValueClass && sel.symbol == tpt.tpe.typeSymbol.firstParamAccessor => Some(arg) case _ => @@ -398,7 +398,7 @@ abstract class Erasure extends AddInterfaces /** An extractor object for boxed expressions (maybe subsumed by posterasure?) */ object Boxed { def unapply(tree: Tree): Option[Tree] = tree match { - case Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)) if (tpt.tpe.typeSymbol.isInlineClass) => + case Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)) if (tpt.tpe.typeSymbol.isDerivedValueClass) => Some(arg) case LabelDef(name, params, Boxed(rhs)) => Some(treeCopy.LabelDef(tree, name, params, rhs) setType rhs.tpe) @@ -411,7 +411,7 @@ abstract class Erasure extends AddInterfaces class Eraser(_context: Context) extends Typer(_context) { private def isUnboxedType(tpe: Type) = tpe match { - case ErasedInlineType(_) => true + case ErasedValueType(_) => true case _ => isPrimitiveValueClass(tpe.typeSymbol) } @@ -431,7 +431,7 @@ abstract class Erasure extends AddInterfaces treeCopy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe case _ => val tree1 = tree.tpe match { - case ErasedInlineType(clazz) => + case ErasedValueType(clazz) => tree match { case Unboxed(arg) if arg.tpe.typeSymbol == clazz => log("shortcircuiting unbox -> box "+arg); arg @@ -487,9 +487,9 @@ abstract class Erasure extends AddInterfaces treeCopy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe case _ => val tree1 = pt match { - case ErasedInlineType(clazz) => + case ErasedValueType(clazz) => tree match { - case Boxed(arg) if arg.tpe.isInstanceOf[ErasedInlineType] => + case Boxed(arg) if arg.tpe.isInstanceOf[ErasedValueType] => log("shortcircuiting box -> unbox "+arg) arg case _ => @@ -553,7 +553,7 @@ abstract class Erasure extends AddInterfaces * - `x != y` for != in class Any becomes `!(x equals y)` with equals in class Object. * - x.asInstanceOf[T] becomes x.$asInstanceOf[T] * - x.isInstanceOf[T] becomes x.$isInstanceOf[T] - * - x.isInstanceOf[ErasedInlineType(clazz)] becomes x.isInstanceOf[clazz.tpe] + * - x.isInstanceOf[ErasedValueType(clazz)] becomes x.isInstanceOf[clazz.tpe] * - x.m where m is some other member of Any becomes x.m where m is a member of class Object. * - x.m where x has unboxed value type T and m is not a directly translated member of T becomes T.box(x).m * - x.m where x is a reference type and m is a directly translated member of value type T becomes x.TValue().m @@ -580,7 +580,7 @@ abstract class Erasure extends AddInterfaces case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_isInstanceOf || tree.symbol == Object_asInstanceOf => targ.tpe match { - case ErasedInlineType(clazz) => targ.setType(clazz.tpe) + case ErasedValueType(clazz) => targ.setType(clazz.tpe) case _ => } tree @@ -967,7 +967,7 @@ abstract class Erasure extends AddInterfaces else tree - case Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)) if (tpt.tpe.typeSymbol.isInlineClass) => + case Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)) if (tpt.tpe.typeSymbol.isDerivedValueClass) => arg case Apply(fn, args) => def qualifier = fn match { @@ -1063,7 +1063,7 @@ abstract class Erasure extends AddInterfaces case Literal(ct) if ct.tag == ClassTag && ct.typeValue.typeSymbol != definitions.UnitClass => val erased = ct.typeValue match { - case TypeRef(pre, clazz, args) if clazz.isInlineClass => scalaErasure.eraseNormalClassRef(pre, clazz) + case TypeRef(pre, clazz, args) if clazz.isDerivedValueClass => scalaErasure.eraseNormalClassRef(pre, clazz) case tpe => specialScalaErasure(tpe) } treeCopy.Literal(tree, Constant(erased)) diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 79dc6b4986..3e86c74c57 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -1,9 +1,7 @@ /* NSC -- new Scala compiler * Copyright 2005-2011 LAMP/EPFL - * @author Gilles Dubochet * @author Martin Odersky */ - package scala.tools.nsc package transform @@ -16,7 +14,8 @@ import scala.runtime.ScalaRunTime.{ isAnyVal, isTuple } import sun.tools.tree.OrExpression /** - * Perform Step 1 in the inline classes SIP + * Perform Step 1 in the inline classes SIP: Creates extension methods for all + * methods in a value class, except parameter or super accessors, or constructors. * * @author Martin Odersky * @version 2.10 @@ -101,7 +100,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { override def transform(tree: Tree): Tree = { tree match { case Template(_, _, _) => - if (currentOwner.isInlineClass) { + if (currentOwner.isDerivedValueClass) { extensionDefs(currentOwner.companionModule) = new mutable.ListBuffer[Tree] super.transform(tree) } @@ -115,7 +114,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { companion.info.decls.enter(extensionMeth) val newInfo = extensionMethInfo(extensionMeth, origMeth.info, currentOwner) extensionMeth setInfo newInfo - log("Inline class %s spawns extension method.\n Old: %s\n New: %s".format( + log("Value class %s spawns extension method.\n Old: %s\n New: %s".format( currentOwner, origMeth.defString, extensionMeth.defString)) // extensionMeth.defStringSeenAs(origInfo diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala index af8de11504..ef158a71f6 100644 --- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala +++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala @@ -1,6 +1,13 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2012 LAMP/EPFL + * @author Martin odersky + */ package scala.tools.nsc package transform +/** This phase maps ErasedValueTypes to the underlying unboxed representation and + * performs peephole optimizations. + */ trait PostErasure extends InfoTransform with TypingTransformers { val global: Global @@ -12,25 +19,25 @@ trait PostErasure extends InfoTransform with TypingTransformers { def newTransformer(unit: CompilationUnit): Transformer = new PostErasureTransformer(unit) override def changesBaseClasses = false - object elimErasedInline extends TypeMap { + object elimErasedValueType extends TypeMap { def apply(tp: Type) = tp match { - case ErasedInlineType(clazz) => erasure.underlyingOfValueClass(clazz) + case ErasedValueType(clazz) => erasure.underlyingOfValueClass(clazz) case _ => mapOver(tp) } } - def transformInfo(sym: Symbol, tp: Type) = elimErasedInline(tp) + def transformInfo(sym: Symbol, tp: Type) = elimErasedValueType(tp) class PostErasureTransformer(unit: CompilationUnit) extends TypingTransformer(unit) { override def transform(tree: Tree) = - super.transform(tree) setType elimErasedInline(tree.tpe) match { + super.transform(tree) setType elimErasedValueType(tree.tpe) match { case // new C(arg).underlying ==> arg Apply(sel @ Select( Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)), acc), List()) if atPhase(currentRun.erasurePhase) { - tpt.tpe.typeSymbol.isInlineClass && + tpt.tpe.typeSymbol.isDerivedValueClass && sel.symbol == tpt.tpe.typeSymbol.firstParamAccessor } => if (settings.debug.value) log("Removing "+tree+" -> "+arg) @@ -41,7 +48,7 @@ trait PostErasure extends InfoTransform with TypingTransformers { cmp), List(Apply(Select(New(tpt2), nme.CONSTRUCTOR), List(arg2)))) if atPhase(currentRun.erasurePhase) { - tpt1.tpe.typeSymbol.isInlineClass && + tpt1.tpe.typeSymbol.isDerivedValueClass && (cmp == nme.EQ || cmp == nme.NE) && tpt2.tpe.typeSymbol == tpt1.tpe.typeSymbol } => @@ -58,4 +65,4 @@ trait PostErasure extends InfoTransform with TypingTransformers { tree1 } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index dcf5005538..9027b6039c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1263,7 +1263,7 @@ trait Namers extends MethodSynthesis { val clazz = tree.symbol val result = createNamer(tree).classSig(tparams, impl) clazz setInfo result - if (clazz.isInlineClass) { + if (clazz.isDerivedValueClass) { clazz setFlag FINAL ensureCompanionObject(cdef) } diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index e0b4072fa1..9bee731e1e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -159,7 +159,7 @@ trait SyntheticMethods extends ast.TreeDSL { val otherSym = eqmeth.newValue(otherName, eqmeth.pos, SYNTHETIC) setInfo clazz.tpe val pairwise = accessors map (acc => fn(Select(This(clazz), acc), acc.tpe member nme.EQ, Select(Ident(otherSym), acc))) val canEq = gen.mkMethodCall(otherSym, nme.canEqual_, Nil, List(This(clazz))) - val tests = if (clazz.isInlineClass || clazz.isFinal && syntheticCanEqual) pairwise else pairwise :+ canEq + val tests = if (clazz.isDerivedValueClass || clazz.isFinal && syntheticCanEqual) pairwise else pairwise :+ canEq thatTest(eqmeth) AND Block( ValDef(otherSym, thatCast(eqmeth)), @@ -192,14 +192,14 @@ trait SyntheticMethods extends ast.TreeDSL { * val x$1 = that.asInstanceOf[this.C] * (this.underlying == that.underlying */ - def equalsInlineClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => + def equalsDerivedValueClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => equalsCore(m, List(clazz.firstParamAccessor)) } /** The hashcode method for value classes * def hashCode(): Int = this.underlying.hashCode */ - def hashCodeInlineClassMethod: Tree = createMethod(nme.hashCode_, Nil, IntClass.tpe) { m => + def hashCodeDerivedValueClassMethod: Tree = createMethod(nme.hashCode_, Nil, IntClass.tpe) { m => Select( Select(This(clazz), clazz.firstParamAccessor), nme.hashCode_) @@ -240,8 +240,8 @@ trait SyntheticMethods extends ast.TreeDSL { ) def inlineClassMethods = List( - Any_hashCode -> (() => hashCodeInlineClassMethod), - Any_equals -> (() => equalsInlineClassMethod) + Any_hashCode -> (() => hashCodeDerivedValueClassMethod), + Any_equals -> (() => equalsDerivedValueClassMethod) ) /** If you serialize a singleton and then deserialize it twice, @@ -258,7 +258,7 @@ trait SyntheticMethods extends ast.TreeDSL { def synthesize(): List[Tree] = { val methods = ( - if (clazz.isInlineClass) inlineClassMethods + if (clazz.isDerivedValueClass) inlineClassMethods else if (!clazz.isCase) Nil else if (clazz.isModuleClass) caseObjectMethods else caseClassMethods diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index fde9b6f551..02b7dae544 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1193,7 +1193,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - private def validateInlineClass(clazz: Symbol, body: List[Tree]) = { + private def validateDerivedValueClass(clazz: Symbol, body: List[Tree]) = { if (clazz.isTrait) unit.error(clazz.pos, "Only classes (not traits) are allowed to extend AnyVal") if (!clazz.isStatic) @@ -1213,7 +1213,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (stat.symbol hasFlag PARAMACCESSOR) "Illegal parameter for value class" else "This statement is not allowed in value class: "+stat) case x => - unit.error(clazz.pos, "Value class needs to have exactly one public val parameter") + println(clazz.info.decls.toList) + unit.error(clazz.pos, "Value class needs to have exactly one public val parameter, found: "+x.mkString(", ")) } for (tparam <- clazz.typeParams) if (tparam hasAnnotation definitions.SpecializedClass) @@ -1573,8 +1574,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val body1 = typedStats(body, templ.symbol) - if (clazz.isInlineClass) - validateInlineClass(clazz, body1) + if (clazz.isDerivedValueClass) + validateDerivedValueClass(clazz, body1) treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe } |