summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-06-25 21:25:12 +0000
committerPaul Phillips <paulp@improving.org>2011-06-25 21:25:12 +0000
commit924b5852faaf9074c3ba74631ad694fcc14f708a (patch)
treeb675db2aa92012e7f66fc0806f0652fe3650e975 /src
parent81964737687fbf8defd3c5798a48309ea19ac7ad (diff)
downloadscala-924b5852faaf9074c3ba74631ad694fcc14f708a.tar.gz
scala-924b5852faaf9074c3ba74631ad694fcc14f708a.tar.bz2
scala-924b5852faaf9074c3ba74631ad694fcc14f708a.zip
Generalizing some TreeGen machinery on an oppor...
Generalizing some TreeGen machinery on an opportunistic basis. Better documenting how Class types and classOf are implemented. Cleaning up the manifest code. No review.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala4
-rw-r--r--src/compiler/scala/reflect/internal/StdNames.scala1
-rw-r--r--src/compiler/scala/reflect/internal/TreeGen.scala38
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala33
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala26
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala21
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala8
9 files changed, 97 insertions, 49 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index ce869cfd3d..9dd20cee95 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -247,8 +247,6 @@ trait Definitions /*extends reflect.generic.StandardDefinitions*/ {
def arrayLengthMethod = getMember(ScalaRunTimeModule, "array_length")
def arrayCloneMethod = getMember(ScalaRunTimeModule, "array_clone")
def ensureAccessibleMethod = getMember(ScalaRunTimeModule, "ensureAccessible")
- def scalaRuntimeHash = getMember(ScalaRunTimeModule, "hash")
- def scalaRuntimeAnyValClass = getMember(ScalaRunTimeModule, "anyValClass")
def scalaRuntimeSameElements = getMember(ScalaRunTimeModule, nme.sameElements)
// classes with special meanings
@@ -489,7 +487,7 @@ trait Definitions /*extends reflect.generic.StandardDefinitions*/ {
def ClassType(arg: Type) =
if (phase.erasedTypes || forMSIL) ClassClass.tpe
- else appliedType(ClassClass.tpe, List(arg))
+ else appliedType(ClassClass.typeConstructor, List(arg))
//
// .NET backend
diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala
index a31dc30f48..991cc1e1b5 100644
--- a/src/compiler/scala/reflect/internal/StdNames.scala
+++ b/src/compiler/scala/reflect/internal/StdNames.scala
@@ -189,6 +189,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy
// val productElementName: NameType = "productElementName"
val TYPE_ : NameType = "TYPE"
val add_ : NameType = "add"
+ val anyValClass: NameType = "anyValClass"
val apply: NameType = "apply"
val arrayValue: NameType = "arrayValue"
val arraycopy: NameType = "arraycopy"
diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala
index 379782c615..9d48d9d299 100644
--- a/src/compiler/scala/reflect/internal/TreeGen.scala
+++ b/src/compiler/scala/reflect/internal/TreeGen.scala
@@ -24,6 +24,33 @@ abstract class TreeGen {
AppliedTypeTree(cls, argtpes :+ restpe)
}
+ /** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...)
+ * There are a number of variations.
+ *
+ * @param receiver symbol of the method receiver
+ * @param methodName name of the method to call
+ * @param targs type arguments (if Nil, no TypeApply node will be generated)
+ * @param args value arguments
+ * @return the newly created trees.
+ */
+ def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree =
+ mkMethodCall(Select(mkAttributedRef(receiver), methodName), targs, args)
+ def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree =
+ mkMethodCall(mkAttributedRef(method), targs, args)
+ def mkMethodCall(method: Symbol, args: List[Tree]): Tree =
+ mkMethodCall(method, Nil, args)
+ def mkMethodCall(target: Tree, args: List[Tree]): Tree =
+ mkMethodCall(target, Nil, args)
+ def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree =
+ mkMethodCall(receiver, methodName, Nil, args)
+ def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree =
+ mkMethodCall(Select(receiver, method), targs, args)
+
+ def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree = {
+ val typeApplied = if (targs.isEmpty) target else TypeApply(target, targs map TypeTree)
+ Apply(typeApplied, args)
+ }
+
/** Builds a reference to value whose type is given stable prefix.
* The type must be suitable for this. For example, it
* must not be a TypeRef pointing to an abstract type variable.
@@ -191,8 +218,17 @@ abstract class TreeGen {
mkAsInstanceOf(tree, pt)
}
+ /** Apparently we smuggle a Type around as a Literal(Constant(tp))
+ * and the implementation of Constant#tpe is such that x.tpe becomes
+ * ClassType(value.asInstanceOf[Type]), i.e. java.lang.Class[Type].
+ * Can't find any docs on how/why it's done this way. See ticket
+ * SI-490 for some interesting comments from lauri alanko suggesting
+ * that the type given by classOf[T] is too strong and should be
+ * weakened so as not to suggest that classOf[List[String]] is any
+ * different from classOf[List[Int]].
+ */
def mkClassOf(tp: Type): Tree =
- Literal(Constant(tp)) setType ConstantType(Constant(tp))// ClassType(tp)
+ Literal(Constant(tp)) setType ConstantType(Constant(tp))
/** Builds a list with given head and tail. */
def mkNewCons(head: Tree, tail: Tree): Tree =
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index 35b1fc3ee8..177a89d9ae 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -84,10 +84,29 @@ abstract class TreeGen extends reflect.internal.TreeGen {
DefDef(accessor setFlag lateDEFERRED, EmptyTree)
def mkRuntimeCall(meth: Name, args: List[Tree]): Tree =
- Apply(Select(mkAttributedRef(ScalaRunTimeModule), meth), args)
+ mkRuntimeCall(meth, Nil, args)
def mkRuntimeCall(meth: Name, targs: List[Type], args: List[Tree]): Tree =
- Apply(TypeApply(Select(mkAttributedRef(ScalaRunTimeModule), meth), targs map TypeTree), args)
+ mkMethodCall(ScalaRunTimeModule, meth, targs, args)
+
+ def mkSysErrorCall(message: String): Tree =
+ mkMethodCall(Sys_error, List(Literal(message)))
+
+ /** A creator for a call to a scala.reflect.Manifest or ClassManifest factory method.
+ *
+ * @param full full or partial manifest (target will be Manifest or ClassManifest)
+ * @param constructor name of the factory method (e.g. "classType")
+ * @param tparg the type argument
+ * @param args value arguments
+ * @return the tree
+ */
+ def mkManifestFactoryCall(full: Boolean, constructor: String, tparg: Type, args: List[Tree]): Tree =
+ mkMethodCall(
+ if (full) FullManifestModule else PartialManifestModule,
+ constructor,
+ List(tparg),
+ args
+ )
/** Make a synchronized block on 'monitor'. */
def mkSynchronized(monitor: Tree, body: Tree): Tree =
@@ -123,10 +142,12 @@ abstract class TreeGen extends reflect.internal.TreeGen {
else if ((elemtp <:< AnyRefClass.tpe) && !isPhantomClass(sym)) "wrapRefArray"
else "genericWrapArray"
- if (isValueClass(sym))
- Apply(Select(mkAttributedRef(PredefModule), meth), List(tree))
- else
- Apply(TypeApply(Select(mkAttributedRef(PredefModule), meth), List(TypeTree(elemtp))), List(tree))
+ mkMethodCall(
+ PredefModule,
+ meth,
+ if (isValueClass(sym)) Nil else List(elemtp),
+ List(tree)
+ )
}
/** Generate a cast for tree Tree representing Array with
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index aa829d61ab..86afd8f078 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -199,8 +199,6 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
val reflClassCacheSym: Symbol =
addStaticVariableToClass("reflClass$Cache", SoftReferenceClass.tpe, NULL, false)
- def getMethodSym = ClassClass.tpe member nme.getMethod_
-
def isCacheEmpty(receiver: Symbol): Tree =
reflClassCacheSym.IS_NULL() OR (reflClassCacheSym.GET() OBJ_NE REF(receiver))
@@ -208,7 +206,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
case Pair(reflMethodSym, List(forReceiverSym)) =>
BLOCK(
IF (isCacheEmpty(forReceiverSym)) THEN BLOCK(
- safeREF(reflMethodCacheSym) === ((REF(forReceiverSym) DOT getMethodSym)(LIT(method), safeREF(reflParamsCacheSym))) ,
+ safeREF(reflMethodCacheSym) === ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))) ,
safeREF(reflClassCacheSym) === gen.mkSoftRef(REF(forReceiverSym)),
UNIT
) ENDIF,
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index a06812084e..5452dc70a2 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -70,9 +70,8 @@ abstract class Erasure extends AddInterfaces
// type of getClass calls. The returned type is:
//
// 1. If T is a value type, Class[T].
- // 2. If T is anonymous or a refinement type, calculate the intersection
- // dominator of the parents T', and Class[_ <: T'].
- // 3. If T is a phantom type (Any or AnyVal), Class[_].
+ // 2. If T is a phantom type (Any or AnyVal), Class[_].
+ // 3. If T is a local class, Class[_ <: |T|].
// 4. Otherwise, Class[_ <: T].
//
// Note: AnyVal cannot be Class[_ <: AnyVal] because if the static type of the
@@ -81,20 +80,21 @@ abstract class Erasure extends AddInterfaces
//
// TODO: If T is final, return type could be Class[T]. Should it?
def getClassReturnType(tp: Type): Type = {
- def mkClass(targs: List[Type]) = typeRef(ClassClass.tpe.prefix, ClassClass, targs)
- val tparams = ClassClass.typeParams
val sym = tp.typeSymbol
- if (tparams.isEmpty) mkClass(Nil) // call must be coming post-erasure
- else if (isValueClass(sym)) mkClass(List(tp.widen))
- else if (sym.isLocalClass) getClassReturnType(erasure.intersectionDominator(tp.parents))
+ if (phase.erasedTypes) ClassClass.tpe
+ else if (isValueClass(sym)) ClassType(tp.widen)
else {
- val eparams = typeParamsToExistentials(ClassClass, tparams)
- val upperBound = if (isPhantomClass(sym)) AnyClass.tpe else tp.widen
+ val eparams = typeParamsToExistentials(ClassClass, ClassClass.typeParams)
+ val upperBound = (
+ if (isPhantomClass(sym)) AnyClass.tpe
+ else if (sym.isLocalClass) erasure.intersectionDominator(tp.parents) // erasure(tp)
+ else tp.widen
+ )
existentialAbstraction(
eparams,
- mkClass(List(eparams.head setInfo TypeBounds.upper(upperBound) tpe))
+ ClassType(eparams.head setInfo TypeBounds.upper(upperBound) tpe)
)
}
}
@@ -1040,12 +1040,12 @@ abstract class Erasure extends AddInterfaces
case s @ (ShortClass | ByteClass | CharClass) => numericConversion(qual, s)
case BooleanClass => If(qual, LIT(true.##), LIT(false.##))
case _ =>
- Apply(gen.mkAttributedRef(scalaRuntimeHash), List(qual))
+ global.typer.typed(gen.mkRuntimeCall(nme.hash_, List(qual)))
}
}
// Rewrite 5.getClass to ScalaRunTime.anyValClass(5)
else if (isValueClass(qual.tpe.typeSymbol))
- Apply(gen.mkAttributedRef(scalaRuntimeAnyValClass), List(qual))
+ global.typer.typed(gen.mkRuntimeCall(nme.anyValClass, List(qual)))
else
tree
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 6a6a173e0f..ced2874a14 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -1378,11 +1378,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case NormalizedMember(target) =>
log("Normalized member: " + symbol + ", target: " + target)
if (target.isDeferred || conflicting(typeEnv(symbol))) {
- treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt,
- localTyper.typed(
- Apply(gen.mkAttributedRef(definitions.Sys_error),
- List(Literal("boom! you stepped on a bug. This method should never be called.")))))
- } else {
+ treeCopy.DefDef(
+ tree, mods, name, tparams, vparamss, tpt,
+ localTyper typed gen.mkSysErrorCall("boom! you stepped on a bug. This method should never be called.")
+ )
+ }
+ else {
// we have an rhs, specialize it
val tree1 = duplicateBody(ddef, target)
debuglog("implementation: " + tree1)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 87bde02b94..29ca9f4a70 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1056,15 +1056,7 @@ trait Implicits {
/** Creates a tree that calls the factory method called constructor in object reflect.Manifest */
def manifestFactoryCall(constructor: String, tparg: Type, args: Tree*): Tree =
if (args contains EmptyTree) EmptyTree
- else typedPos(tree.pos.focus) {
- Apply(
- TypeApply(
- Select(gen.mkAttributedRef(if (full) FullManifestModule else PartialManifestModule), constructor),
- List(TypeTree(tparg))
- ),
- args.toList
- )
- }
+ else typedPos(tree.pos.focus)(gen.mkManifestFactoryCall(full, constructor, tparg, args.toList))
/** Creates a tree representing one of the singleton manifests.*/
def findSingletonManifest(name: String) = typedPos(tree.pos.focus) {
@@ -1097,13 +1089,12 @@ trait Implicits {
manifestFactoryCall("arrayType", args.head, findManifest(args.head))
} else if (sym.isClass) {
val classarg0 = gen.mkClassOf(tp1)
- val classarg = tp match {
- case ExistentialType(_, _) =>
- TypeApply(Select(classarg0, Any_asInstanceOf),
- List(TypeTree(appliedType(ClassClass.typeConstructor, List(tp)))))
- case _ =>
+ val classarg = (
+ if (tp.isInstanceOf[ExistentialType])
+ TypeApply(Select(classarg0, Any_asInstanceOf), List(TypeTree(ClassType(tp))))
+ else
classarg0
- }
+ )
val suffix = classarg :: (args map findSubManifest)
manifestFactoryCall(
"classType", tp,
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 40e3aea1d7..6ff1302888 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1265,7 +1265,7 @@ abstract class RefChecks extends InfoTransform {
}
}
val newResult = localTyper.typedPos(tree.pos) {
- new ApplyToImplicitArgs(Apply(Select(gen.mkAttributedRef(ArrayModule), nme.ofDim), args), List(manif))
+ new ApplyToImplicitArgs(gen.mkMethodCall(ArrayModule, nme.ofDim, args), List(manif))
}
currentApplication = tree
newResult
@@ -1336,8 +1336,10 @@ abstract class RefChecks extends InfoTransform {
var result: Tree = tree match {
case DefDef(mods, name, tparams, vparams, tpt, EmptyTree) if tree.symbol.hasAnnotation(NativeAttr) =>
tree.symbol.resetFlag(DEFERRED)
- transform(treeCopy.DefDef(tree, mods, name, tparams, vparams, tpt,
- typed(Apply(gen.mkAttributedRef(Sys_error), List(Literal("native method stub"))))))
+ transform(treeCopy.DefDef(
+ tree, mods, name, tparams, vparams, tpt,
+ typed(gen.mkSysErrorCall("native method stub"))
+ ))
case ValDef(_, _, _, _) | DefDef(_, _, _, _, _, _) =>
checkDeprecatedOvers(tree)