diff options
-rw-r--r-- | src/compiler/scala/reflect/internal/Definitions.scala | 14 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala (renamed from src/compiler/scala/tools/nsc/transform/ClassInliner.scala) | 84 | ||||
-rw-r--r-- | src/library/scala/AnyVal.scala | 3 | ||||
-rw-r--r-- | test/files/pos/anyval-children.flags | 1 | ||||
-rw-r--r-- | test/files/pos/anyval-children.scala (renamed from test/disabled/pos/anyval-children.scala) | 0 |
7 files changed, 62 insertions, 50 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index e8fc1c9cc9..715a68cf55 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -659,6 +659,15 @@ trait Definitions extends reflect.api.StandardDefinitions { AnyClass, nme.isInstanceOf_, tparam => NullaryMethodType(booltype)) setFlag FINAL lazy val Any_asInstanceOf = newPolyMethod( AnyClass, nme.asInstanceOf_, tparam => NullaryMethodType(tparam.typeConstructor)) setFlag FINAL + + // AnyVal_getClass is defined here. Once we have a new strap, it could also be + // defined directly in the AnyVal trait. Right now this does not work, because + // strap complains about overriding a final getClass method in Any. + lazy val AnyVal_getClass = { + val m = AnyValClass.newMethod(nme.getClass_) + val tparam = m.newExistential(newTypeName("T")) setInfo TypeBounds(NothingClass.tpe, AnyValClass.tpe) + m setInfoAndEnter MethodType(List(), ExistentialType(List(tparam), appliedType(ClassClass.typeConstructor, List(tparam.tpe)))) + } // members of class java.lang.{ Object, String } lazy val Object_## = newMethod(ObjectClass, nme.HASHHASH, Nil, inttype, FINAL) @@ -859,7 +868,7 @@ trait Definitions extends reflect.api.StandardDefinitions { val msym = owner.info.decls enter owner.newMethod(name.encode) val tparam = newTypeParam(msym, 0) - msym setInfo GenPolyType(List(tparam), tcon(tparam)(msym)) + msym setInfo PolyType(List(tparam), tcon(tparam)(msym)) } private def newTypeParam(owner: Symbol, index: Int): Symbol = @@ -991,7 +1000,8 @@ trait Definitions extends reflect.api.StandardDefinitions { Object_synchronized, Object_isInstanceOf, Object_asInstanceOf, - String_+ + String_+, + AnyVal_getClass ) /** Removing the anyref parent they acquire from having a source file. diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 1092c7bce1..8026e92a21 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -436,11 +436,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb val global: Global.this.type = Global.this } with Analyzer - object classInlining extends { + object extensionMethods extends { val global: Global.this.type = Global.this val runsAfter = List("typer") val runsRightAfter = None - } with ClassInlining + } with ExtensionMethods // phaseName = "superaccessors" object superAccessors extends { @@ -656,7 +656,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb analyzer.packageObjects -> "load package objects", analyzer.typerFactory -> "the meat and potatoes: type the trees", superAccessors -> "add super accessors in traits and nested classes", - classInlining -> "add static methods to inline classes", + extensionMethods -> "add extension methods for inline classes", pickler -> "serialize symbol tables", refChecks -> "reference/override checking, translate nested objects", liftcode -> "reify trees", diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 51941408a2..5b1555bfb7 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -986,8 +986,8 @@ abstract class Erasure extends AddInterfaces } } else if (fn.symbol.owner.isRefinementClass && !fn.symbol.isOverridingSymbol) { ApplyDynamic(qualifier, args) setSymbol fn.symbol setPos tree.pos - } else if (fn.symbol.owner.isInlineClass && classInlining.hasUnboxedVersion(fn.symbol)) { - Apply(gen.mkAttributedRef(classInlining.unboxedMethod(fn.symbol)), qualifier :: args) + } else if (fn.symbol.owner.isInlineClass && extensionMethods.hasExtension(fn.symbol)) { + Apply(gen.mkAttributedRef(extensionMethods.extensionMethod(fn.symbol)), qualifier :: args) } else { tree } diff --git a/src/compiler/scala/tools/nsc/transform/ClassInliner.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index c1104b025c..5f62dfab39 100644 --- a/src/compiler/scala/tools/nsc/transform/ClassInliner.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -21,50 +21,50 @@ import sun.tools.tree.OrExpression * @author Martin Odersky * @version 2.10 */ -abstract class ClassInlining extends Transform with TypingTransformers { +abstract class ExtensionMethods extends Transform with TypingTransformers { import global._ // the global environment import definitions._ // standard classes and methods import typer.{ typed, atOwner } // methods to type trees /** the following two members override abstract members in Transform */ - val phaseName: String = "inlineclasses" + val phaseName: String = "extmethods" def newTransformer(unit: CompilationUnit): Transformer = - new ClassInliner(unit) + new Extender(unit) - def hasUnboxedVersion(sym: Symbol) = + def hasExtension(sym: Symbol) = !sym.isParamAccessor && !sym.isConstructor - /** Generate stream of possible names for the unboxed version of given instance method `imeth`. - * If the method is not overloaded, this stream consists of just "unboxed$imeth". - * If the method is overloaded, the stream has as first element "unboxedX$imeth", where X is the + /** Generate stream of possible names for the extension version of given instance method `imeth`. + * If the method is not overloaded, this stream consists of just "extension$imeth". + * If the method is overloaded, the stream has as first element "extensionX$imeth", where X is the * index of imeth in the sequence of overloaded alternatives with the same name. This choice will - * always be picked as the name of the generated unboxed method. + * always be picked as the name of the generated extension method. * After this first choice, all other possible indices in the range of 0 until the number * of overloaded alternatives are returned. The secondary choices are used to find a matching method - * in `unboxedMethod` if the first name has the wrong type. We thereby gain a level of insensitivity + * in `extensionMethod` if the first name has the wrong type. We thereby gain a level of insensitivity * of how overloaded types are ordered between phases and picklings. */ - private def unboxedNames(imeth: Symbol): Stream[Name] = + private def extensionNames(imeth: Symbol): Stream[Name] = imeth.owner.info.decl(imeth.name).tpe match { case OverloadedType(_, alts) => val index = alts indexOf imeth assert(index >= 0, alts+" does not contain "+imeth) - def altName(index: Int) = newTermName("unboxed"+index+"$"+imeth.name) + def altName(index: Int) = newTermName("extension"+index+"$"+imeth.name) altName(index) #:: ((0 until alts.length).toStream filter (index !=) map altName) case tpe => assert(tpe != NoType, imeth.name+" not found in "+imeth.owner+"'s decls: "+imeth.owner.info.decls) - Stream(newTermName("unboxed$"+imeth.name)) + Stream(newTermName("extension$"+imeth.name)) } - /** Return the unboxed method that corresponds to given instance method `meth`. + /** Return the extension method that corresponds to given instance method `meth`. */ - def unboxedMethod(imeth: Symbol): Symbol = atPhase(currentRun.refchecksPhase) { + def extensionMethod(imeth: Symbol): Symbol = atPhase(currentRun.refchecksPhase) { val companionInfo = imeth.owner.companionModule.info - val candidates = unboxedNames(imeth) map (companionInfo.decl(_)) + val candidates = extensionNames(imeth) map (companionInfo.decl(_)) val matching = candidates filter (alt => normalize(alt.tpe, imeth.owner) matches imeth.tpe) - assert(matching.nonEmpty, "no unboxed method found for "+imeth+" among "+candidates+"/"+unboxedNames(imeth)) + assert(matching.nonEmpty, "no extension method found for "+imeth+" among "+candidates+"/"+extensionNames(imeth)) matching.head } @@ -77,21 +77,21 @@ abstract class ClassInlining extends Transform with TypingTransformers { stpe } - class ClassInliner(unit: CompilationUnit) extends TypingTransformer(unit) { + class Extender(unit: CompilationUnit) extends TypingTransformer(unit) { - private val unboxedDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]() + private val extensionDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]() - def unboxedMethInfo(unboxedMeth: Symbol, origInfo: Type, clazz: Symbol): Type = { - var newTypeParams = cloneSymbolsAtOwner(clazz.typeParams, unboxedMeth) + def extensionMethInfo(extensionMeth: Symbol, origInfo: Type, clazz: Symbol): Type = { + var newTypeParams = cloneSymbolsAtOwner(clazz.typeParams, extensionMeth) val thisParamType = appliedType(clazz.typeConstructor, newTypeParams map (_.tpe)) - val thisParam = unboxedMeth.newValueParameter(nme.SELF, unboxedMeth.pos) setInfo thisParamType + val thisParam = extensionMeth.newValueParameter(nme.SELF, extensionMeth.pos) setInfo thisParamType def transform(clonedType: Type): Type = clonedType match { case MethodType(params, restpe) => MethodType(List(thisParam), clonedType) case NullaryMethodType(restpe) => MethodType(List(thisParam), restpe) } - val GenPolyType(tparams, restpe) = origInfo cloneInfo unboxedMeth + val GenPolyType(tparams, restpe) = origInfo cloneInfo extensionMeth GenPolyType(tparams ::: newTypeParams, transform(restpe)) } @@ -104,41 +104,41 @@ abstract class ClassInlining extends Transform with TypingTransformers { tree match { case Template(_, _, _) => if (currentOwner.isInlineClass) { - unboxedDefs(currentOwner.companionModule) = new mutable.ListBuffer[Tree] + extensionDefs(currentOwner.companionModule) = new mutable.ListBuffer[Tree] super.transform(tree) } else tree case DefDef(mods, name, tparams, vparamss, tpt, rhs) - if currentOwner.isInlineClass && hasUnboxedVersion(tree.symbol) => + if currentOwner.isInlineClass && hasExtension(tree.symbol) => val companion = currentOwner.companionModule val origMeth = tree.symbol - val unboxedName = unboxedNames(origMeth).head - val unboxedMeth = companion.moduleClass.newMethod(unboxedName, origMeth.pos, origMeth.flags & ~OVERRIDE | FINAL) + val extensionName = extensionNames(origMeth).head + val extensionMeth = companion.moduleClass.newMethod(extensionName, origMeth.pos, origMeth.flags & ~OVERRIDE | FINAL) .setAnnotations(origMeth.annotations) - companion.info.decls.enter(unboxedMeth) - unboxedMeth.setInfo(unboxedMethInfo(unboxedMeth, origMeth.info, currentOwner)) - def thisParamRef = gen.mkAttributedIdent(unboxedMeth.info.params.head setPos unboxedMeth.pos) - val GenPolyType(unboxedTpeParams, unboxedMono) = unboxedMeth.info + companion.info.decls.enter(extensionMeth) + extensionMeth.setInfo(extensionMethInfo(extensionMeth, origMeth.info, currentOwner)) + def thisParamRef = gen.mkAttributedIdent(extensionMeth.info.params.head setPos extensionMeth.pos) + val GenPolyType(extensionTpeParams, extensionMono) = extensionMeth.info val origTpeParams = origMeth.typeParams ::: currentOwner.typeParams - val unboxedBody = rhs - .substTreeSyms(origTpeParams, unboxedTpeParams) - .substTreeSyms(vparamss.flatten map (_.symbol), allParams(unboxedMono).tail) + val extensionBody = rhs + .substTreeSyms(origTpeParams, extensionTpeParams) + .substTreeSyms(vparamss.flatten map (_.symbol), allParams(extensionMono).tail) .substTreeThis(currentOwner, thisParamRef) - .changeOwner((origMeth, unboxedMeth)) - unboxedDefs(companion) += atPos(tree.pos) { DefDef(unboxedMeth, unboxedBody) } - val unboxedCallPrefix = Apply( - gen.mkTypeApply(gen.mkAttributedRef(companion), unboxedMeth, origTpeParams map (_.tpe)), + .changeOwner((origMeth, extensionMeth)) + extensionDefs(companion) += atPos(tree.pos) { DefDef(extensionMeth, extensionBody) } + val extensionCallPrefix = Apply( + gen.mkTypeApply(gen.mkAttributedRef(companion), extensionMeth, origTpeParams map (_.tpe)), List(This(currentOwner))) - val unboxedCall = atOwner(origMeth) { + val extensionCall = atOwner(origMeth) { localTyper.typed { atPos(rhs.pos) { - (unboxedCallPrefix /: vparamss) { + (extensionCallPrefix /: vparamss) { case (fn, params) => Apply(fn, params map (param => Ident(param.symbol))) } } } } - treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, unboxedCall) + treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, extensionCall) case _ => super.transform(tree) } @@ -147,9 +147,9 @@ abstract class ClassInlining extends Transform with TypingTransformers { override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = super.transformStats(stats, exprOwner) map { case stat @ ModuleDef(mods, name, tmpl @ Template(parents, self, body)) => - unboxedDefs.remove(stat.symbol) match { + extensionDefs.remove(stat.symbol) match { case Some(buf) => - val unboxedDefs = buf.toList map { mdef => atOwner(stat.symbol) { localTyper.typed(mdef) }} + val extensionDefs = buf.toList map { mdef => atOwner(stat.symbol) { localTyper.typed(mdef) }} treeCopy.ModuleDef(stat, mods, name, treeCopy.Template(tmpl, parents, self, body ++ buf)) case None => stat diff --git a/src/library/scala/AnyVal.scala b/src/library/scala/AnyVal.scala index ed4c5f5948..fb36d61c57 100644 --- a/src/library/scala/AnyVal.scala +++ b/src/library/scala/AnyVal.scala @@ -26,6 +26,7 @@ package scala * The ''floating point types'' are [[scala.Float]] and [[scala.Double]]. */ trait AnyVal { -// disabled for now to make the standard build go through +// 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/pos/anyval-children.flags b/test/files/pos/anyval-children.flags new file mode 100644 index 0000000000..80fce051e6 --- /dev/null +++ b/test/files/pos/anyval-children.flags @@ -0,0 +1 @@ +-Ystop-after:erasure
\ No newline at end of file diff --git a/test/disabled/pos/anyval-children.scala b/test/files/pos/anyval-children.scala index 7a2eda8b3f..7a2eda8b3f 100644 --- a/test/disabled/pos/anyval-children.scala +++ b/test/files/pos/anyval-children.scala |