summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-03-12 15:28:40 +0000
committerMartin Odersky <odersky@gmail.com>2007-03-12 15:28:40 +0000
commitc0ab376dd8c1ca891d68490083629780faecfcdf (patch)
treeab1d14a9ec82adbcb9ff6249de732f623483747c
parent31af03b80e39f171033453ccd5fec7a3d7bf152a (diff)
downloadscala-c0ab376dd8c1ca891d68490083629780faecfcdf.tar.gz
scala-c0ab376dd8c1ca891d68490083629780faecfcdf.tar.bz2
scala-c0ab376dd8c1ca891d68490083629780faecfcdf.zip
fixed bugs 910 and 995.
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala48
-rw-r--r--src/library/scala/Seq.scala6
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala2
5 files changed, 39 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index 2ff4b41266..15033d83e8 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -169,6 +169,12 @@ abstract class TreeGen {
if (elems.isEmpty) Literal(())
else Apply(mkAttributedRef(definitions.TupleClass(elems.length).caseFactory), elems)
+ def mkAnd(tree1: Tree, tree2: Tree) =
+ Apply(Select(tree1, Boolean_and), List(tree2))
+
+ def mkOr(tree1: Tree, tree2: Tree) =
+ Apply(Select(tree1, Boolean_or), List(tree2))
+
def mkCached(cvar: Symbol, expr: Tree): Tree = {
val cvarRef = if (cvar.owner.isClass) Select(This(cvar.owner), cvar) else Ident(cvar)
Block(
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index c8bea1c5fc..f3aedf5e9b 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -104,6 +104,7 @@ trait Definitions requires SymbolTable {
var ScalaRunTimeModule: Symbol = _
def SeqFactory = getMember(ScalaRunTimeModule, nme.Seq);
def checkDefinedMethod = getMember(ScalaRunTimeModule, "checkDefined")
+ def isArrayMethod = getMember(ScalaRunTimeModule, "isArray")
var RepeatedParamClass: Symbol = _
var ByNameParamClass: Symbol = _
var UnsealedClass: Symbol = _
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 4809882041..d0150971a1 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -164,6 +164,9 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
}
}
+ private def isSeqClass(sym: Symbol) =
+ (SeqClass isNonBottomSubClass sym) && (sym != ObjectClass)
+
// -------- boxing/unboxing --------------------------------------------------------
override def newTyper(context: Context) = new Eraser(context)
@@ -279,7 +282,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
}
}
}
- else if ((SeqClass isNonBottomSubClass pt.symbol) && pt.symbol != ObjectClass)
+ else if (isSeqClass(pt.symbol))
typed {
atPos(tree.pos) {
gen.evalOnce(tree, context.owner, context.unit) { x =>
@@ -403,15 +406,15 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List())
if ((tree.symbol == Any_asInstanceOf || tree.symbol == Any_asInstanceOfErased)) =>
val qual1 = typedQualifier(qual)
- val targClass = targ.tpe.symbol
val qualClass = qual1.tpe.symbol
+ val targClass = targ.tpe.symbol
if (isNumericValueClass(qualClass) && isNumericValueClass(targClass))
// convert numeric type casts
atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List()))
else if (isValueType(targClass) ||
(targClass == ArrayClass && (qualClass isNonBottomSubClass BoxedArrayClass)))
unbox(qual1, targ.tpe)
- else if (targClass == ArrayClass && qualClass == ObjectClass)
+ else if (targClass == ArrayClass && qualClass == ObjectClass || isSeqClass(targClass))
cast(qual1, targ.tpe)
else
tree
@@ -717,7 +720,9 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
EmptyTree
case AliasTypeDef(_, _, _, _) =>
EmptyTree
- case TypeApply(fun, args) if (fun.symbol.owner != AnyClass) =>
+ case TypeApply(fun, args) if (fun.symbol.owner != AnyClass &&
+ fun.symbol != Object_asInstanceOf &&
+ fun.symbol != Object_isInstanceOf) =>
// leave all other type tests/type casts, remove all other type applications
fun
case Apply(fn, args) =>
@@ -743,6 +748,12 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
else if (fn.symbol == Any_isInstanceOf || fn.symbol == Any_isInstanceOfErased)
fn match {
case TypeApply(sel @ Select(qual, name), List(targ)) =>
+ def mkIsInstanceOf(q: () => Tree)(tp: Type): Tree =
+ Apply(
+ TypeApply(
+ Select(q(), Object_isInstanceOf) setPos sel.pos,
+ List(TypeTree(tp) setPos targ.pos)) setPos fn.pos,
+ List()) setPos tree.pos
targ.tpe match {
case SingleType(pre, sym) =>
val cmpOp = if (targ.tpe <:< AnyValClass.tpe) Any_equals else Object_eq
@@ -750,22 +761,23 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
Apply(Select(qual, cmpOp), List(gen.mkAttributedQualifier(targ.tpe)))
}
case RefinedType(parents, decls) if (parents.length >= 2) =>
- gen.evalOnce(qual, currentOwner, unit) {
- q =>
- def mkIsInstanceOf(tp: Type) =
- copy.Apply(tree,
- copy.TypeApply(fn,
- copy.Select(sel, q(), name),
- List(TypeTree(tp))),
- List())
- def mkAnd(tree1: Tree, tree2: Tree) =
- atPos(tree1.pos) {
- Apply(Select(tree1, Boolean_and), List(tree2))
- }
- parents map mkIsInstanceOf reduceRight mkAnd
+ gen.evalOnce(qual, currentOwner, unit) { q =>
+ atPos(tree.pos) {
+ parents map mkIsInstanceOf(q) reduceRight gen.mkAnd
+ }
}
case _ =>
- tree
+ if (isSeqClass(targ.tpe.symbol)) {
+ atPos(tree.pos) {
+ gen.evalOnce(qual, currentOwner, unit) { q =>
+ gen.mkOr(
+ mkIsInstanceOf(q)(targ.tpe),
+ atPos(tree.pos) {
+ Apply(gen.mkAttributedRef(isArrayMethod), List(q()))
+ })
+ }
+ }
+ } else tree
}
case _ => tree
}
diff --git a/src/library/scala/Seq.scala b/src/library/scala/Seq.scala
index 19616c97c3..bdf2db2869 100644
--- a/src/library/scala/Seq.scala
+++ b/src/library/scala/Seq.scala
@@ -28,11 +28,7 @@ object Seq {
* @param x the selector value
* @return sequence wrapped in an option, if this is a Seq, otherwise none
*/
- def unapplySeq[A](x: Any): Option[Seq[A]] = x match {
- case z: Seq[_] => Some(z.asInstanceOf[Seq[A]])
- case z: AnyRef if runtime.ScalaRunTime.isArray(z) => Some(runtime.ScalaRunTime.boxArray(z).asInstanceOf[Seq[A]])
- case _ => None
- }
+ def unapplySeq[A](x: Seq[A]): Option[Seq[A]] = Some(x)
/** Builds a singleton sequence.
*
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index aec184f231..3bb0ca432e 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -29,7 +29,7 @@ object ScalaRunTime {
val DoubleTag = ".Double"
val BooleanTag = ".Boolean"
- def isArray(x:AnyRef): Boolean = x.getClass.isArray
+ def isArray(x:AnyRef): Boolean = x != null && x.getClass.isArray
def isValueTag(tag: String) = tag.charAt(0) == '.'
def isValueClass(clazz: Class) = clazz.isPrimitive()