summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-09-23 15:01:27 +0000
committerMartin Odersky <odersky@gmail.com>2009-09-23 15:01:27 +0000
commit4edbecfe9baaec89ced227f5bd6b92fb1f54e1ec (patch)
tree8cca22855825d03bfdcc7ed50a8362355a24a279
parent0d86d977a3eb153f46c59f348638426b821e006c (diff)
downloadscala-4edbecfe9baaec89ced227f5bd6b92fb1f54e1ec.tar.gz
scala-4edbecfe9baaec89ced227f5bd6b92fb1f54e1ec.tar.bz2
scala-4edbecfe9baaec89ced227f5bd6b92fb1f54e1ec.zip
Fixed #2381.
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala20
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala35
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala8
5 files changed, 50 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index abf7026f3a..219f781605 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -278,6 +278,10 @@ abstract class TreeGen
Apply(Select(mkAttributedRef(ScalaRunTimeModule), meth), args)
}
+ def mkRuntimeCall(meth: Name, targs: List[Type], args: List[Tree]): Tree = {
+ Apply(TypeApply(Select(mkAttributedRef(ScalaRunTimeModule), meth), targs map TypeTree), args)
+ }
+
/** Make a synchronized block on 'monitor'. */
def mkSynchronized(monitor: Tree, body: Tree): Tree =
Apply(Select(monitor, Object_synchronized), List(body))
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 945df94e91..20464f2468 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -821,7 +821,7 @@ trait Trees {
def This(sym: Symbol): Tree = This(sym.name) setSymbol sym
- /** Designator <qualifier> . <selector> */
+ /** Designator <qualifier> . <name> */
case class Select(qualifier: Tree, name: Name)
extends RefTree {
override def isTerm = name.isTermName
@@ -886,7 +886,7 @@ trait Trees {
case class SingletonTypeTree(ref: Tree)
extends TypTree
- /** Type selection <qualifier> # <selector>, eliminated by RefCheck */
+ /** Type selection <qualifier> # <name>, eliminated by RefCheck */
case class SelectFromTypeTree(qualifier: Tree, name: Name)
extends TypTree with RefTree
@@ -909,6 +909,10 @@ trait Trees {
case class Parens(args: List[Tree]) extends Tree // only used during parsing
+ /** Array selection <qualifier> . <name> only used during erasure */
+ case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type)
+ extends TermTree with RefTree
+
trait StubTree extends Tree {
def underlying : AnyRef
override def equalsStructure0(that: Tree)(f : (Tree,Tree) => Boolean): Boolean = this eq that
@@ -1073,6 +1077,7 @@ trait Trees {
def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree
def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree
def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree
+ def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type): SelectFromArray
}
class StrictTreeCopier extends TreeCopier {
@@ -1164,6 +1169,8 @@ trait Trees {
new TypeBoundsTree(lo, hi).copyAttrs(tree)
def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) =
new ExistentialTypeTree(tpt, whereClauses).copyAttrs(tree)
+ def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) =
+ new SelectFromArray(qualifier, selector, erasure).copyAttrs(tree)
}
class LazyTreeCopier(treeCopy: TreeCopier) extends TreeCopier {
@@ -1388,6 +1395,11 @@ trait Trees {
if (tpt0 == tpt) && (whereClauses0 == whereClauses) => t
case _ => treeCopy.ExistentialTypeTree(tree, tpt, whereClauses)
}
+ def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) = tree match {
+ case t @ SelectFromArray(qualifier0, selector0, _)
+ if (qualifier0 == qualifier) && (selector0 == selector) => t
+ case _ => treeCopy.SelectFromArray(tree, qualifier, selector, erasure)
+ }
}
abstract class Transformer {
@@ -1510,6 +1522,8 @@ trait Trees {
treeCopy.TypeBoundsTree(tree, transform(lo), transform(hi))
case ExistentialTypeTree(tpt, whereClauses) =>
treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses))
+ case SelectFromArray(qualifier, selector, erasure) =>
+ treeCopy.SelectFromArray(tree, transform(qualifier), selector, erasure)
case tree : StubTree =>
tree.symbol = NoSymbol
tree.tpe = null
@@ -1659,6 +1673,8 @@ trait Trees {
traverse(lo); traverse(hi)
case ExistentialTypeTree(tpt, whereClauses) =>
traverse(tpt); traverseTrees(whereClauses)
+ case SelectFromArray(qualifier, selector, erasure) =>
+ traverse(qualifier)
case Parens(ts) =>
traverseTrees(ts)
case tree : StubTree =>
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 39e6a7869c..b6deb501f0 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -2660,7 +2660,8 @@ A type's typeSymbol should never be inspected directly.
private val emptySymCount = scala.collection.immutable.Map[Symbol, Int]()
/** Make an existential variable.
- * @param suffix A suffix to be appended to the freshly generated name
+ * [martin:] this should get moved to Symbols where the other symbols are created.
+ * @param name suffix to be appended to the freshly generated name
* It's ususally "", except for type variables abstracting
* over values, where it is ".type".
* @param owner The owner of the variable
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index c9eb666bfb..e447921beb 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -116,15 +116,6 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
case st: SubType =>
apply(st.supertype)
case TypeRef(pre, sym, args) =>
- def isGeneric(tp: Type): Boolean = tp match {
- case TypeRef(pre, sym, args) =>
- sym.isAbstractType && !(sym.owner hasFlag JAVA) ||
- sym == ArrayClass && args.length == 1 && isGeneric(args.head)
- case ExistentialType(tparams, restp) =>
- isGeneric(restp)
- case _ =>
- false
- }
if (sym == ArrayClass)
if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe
else if (args.head.typeSymbol == NothingClass || args.head.typeSymbol == NullClass) arrayType(ObjectClass.tpe)
@@ -406,7 +397,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
sym.tpe.resultType <:< bridge.tpe.resultType
}
-// -------- boxing/unboxing --------------------------------------------------------
+// -------- erasure on trees ------------------------------------------
override def newTyper(context: Context) = new Eraser(context)
@@ -597,11 +588,15 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
assert(qual1.symbol.isStable, qual1.symbol);
qual1 = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType
} else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) {
- // println("member cast "+tree.symbol+" "+tree.symbol.ownerChain+" "+qual1+" "+qual1.tpe)
+ assert(tree.symbol.owner != ArrayClass)
qual1 = cast(qual1, tree.symbol.owner.tpe)
}
treeCopy.Select(tree, qual1, name)
}
+ case SelectFromArray(qual, name, erasure) =>
+ var qual1 = typedQualifier(qual)
+ if (!(qual1.tpe <:< erasure)) qual1 = cast(qual1, erasure)
+ Select(qual1, name) copyAttrs tree
case _ =>
tree
}
@@ -638,6 +633,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
}
def adaptBranch(branch: Tree): Tree =
if (branch == EmptyTree) branch else adaptToType(branch, tree1.tpe);
+
tree1 match {
case If(cond, thenp, elsep) =>
treeCopy.If(tree1, cond, adaptBranch(thenp), adaptBranch(elsep))
@@ -925,11 +921,18 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
fun.symbol != Object_isInstanceOf) =>
// leave all other type tests/type casts, remove all other type applications
fun
- case Apply(fn @ Select(qual, name), args)
- if (fn.symbol.owner == ArrayClass && (unboundedGenericArrayLevel(qual.tpe.widen) == 1)) =>
- // convert calls to apply/update/length on generic arrays to
- // calls of ScalaRunTime.array_xxx method calls
- typedPos(tree.pos) { gen.mkRuntimeCall("array_"+name, qual :: args) }
+ case Apply(fn @ Select(qual, name), args) if (fn.symbol.owner == ArrayClass) =>
+ if (unboundedGenericArrayLevel(qual.tpe.widen) == 1)
+ // convert calls to apply/update/length on generic arrays to
+ // calls of ScalaRunTime.array_xxx method calls
+ typedPos(tree.pos) { gen.mkRuntimeCall("array_"+name, qual :: args) }
+ else
+ // store exact array erasure in map to be retrieved later when we might
+ // need to do the cast in adaptMember
+ treeCopy.Apply(
+ tree,
+ SelectFromArray(qual, name, erasure(qual.tpe)).copyAttrs(fn),
+ args)
case Apply(fn, args) =>
if (fn.symbol == Any_asInstanceOf)
fn match {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 6a1bdc5ce1..d3f568ef1b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3570,9 +3570,15 @@ trait Typers { self: Analyzer =>
case Typed(expr, tpt) =>
if (treeInfo.isWildcardStarArg(tree)) {
val expr0 = typed(expr, mode & stickyModes, WildcardType)
+ def subArrayType(pt: Type) =
+ if (isValueClass(pt.typeSymbol) || !isFullyDefined(pt)) arrayType(pt)
+ else {
+ val tparam = makeFreshExistential("", context.owner, TypeBounds(NothingClass.tpe, pt))
+ ExistentialType(List(tparam), arrayType(tparam.tpe))
+ }
val (expr1, baseClass) =
if (expr0.tpe.typeSymbol == ArrayClass)
- (adapt(expr0, mode & stickyModes, arrayType(pt)), ArrayClass)
+ (adapt(expr0, mode & stickyModes, subArrayType(pt)), ArrayClass)
else
(adapt(expr0, mode & stickyModes, seqType(pt)), SeqClass)
expr1.tpe.baseType(baseClass) match {