summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala14
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala4
-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.scala3
-rw-r--r--test/files/pos/anyval-children.flags1
-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