diff options
author | James Iry <jamesiry@gmail.com> | 2013-02-27 04:59:47 -0800 |
---|---|---|
committer | James Iry <jamesiry@gmail.com> | 2013-02-28 06:55:32 -0800 |
commit | bfd7863406146aa830028ed77f7b0107fc60e5dc (patch) | |
tree | d035580cd2941d0aca688e0f957189555dd8d84b /src/compiler/scala/tools/nsc | |
parent | 4124a09379fe1784a6069f5af482bdabdb69a569 (diff) | |
download | scala-bfd7863406146aa830028ed77f7b0107fc60e5dc.tar.gz scala-bfd7863406146aa830028ed77f7b0107fc60e5dc.tar.bz2 scala-bfd7863406146aa830028ed77f7b0107fc60e5dc.zip |
SI-7159 Distinguish between assignability and sub typing in TypeKinds
TypeKinds said SHORT <:< INT. But that's not quite true on the JVM. You
can assign SHORT to INT, but you can't assign an ARRAY[SHORT] to
ARRAY[INT]. Since JVM arrays are covariant it's clear that assignability
and subtyping are distinct on the JVM.
This commit adds an isAssignable method and moves the rules about
the int sized primitives there. ICodeCheckers, ICodeReader, and
GenICode are all updated to use isAssignable instead of <:<.
Diffstat (limited to 'src/compiler/scala/tools/nsc')
4 files changed, 20 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 2b513a6fa3..61d0baf7b0 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -1051,7 +1051,7 @@ abstract class GenICode extends SubComponent { case (NothingReference, _) => ctx.bb.emit(THROW(ThrowableClass)) ctx.bb.enterIgnoreMode() - case _ if (from <:< to) => + case _ if from isAssignabledTo to => () case (_, UNIT) => ctx.bb.emit(DROP(from), pos) diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala index fb1ef311d2..49f2d9859d 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala @@ -351,7 +351,7 @@ abstract class ICodeCheckers { def typeError(k1: TypeKind, k2: TypeKind) { icodeError("\n expected: " + k1 + "\n found: " + k2) } - def isSubtype(k1: TypeKind, k2: TypeKind) = (k1 <:< k2) || { + def isSubtype(k1: TypeKind, k2: TypeKind) = (k1 isAssignabledTo k2) || { import platform.isMaybeBoxed (k1, k2) match { diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala index 266e2b861f..1875c8c914 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala @@ -88,17 +88,20 @@ trait TypeKinds { self: ICodes => final def isNumericType: Boolean = isIntegralType | isRealType /** Simple subtyping check */ - def <:<(other: TypeKind): Boolean = other match { - // On the JVM, BOOL, BYTE, CHAR, SHORT need no coercion to INT - // TODO it's pretty suspect to call this a subtyping relationship - // for instance JVM Arrays are covariant, but Array[Char] is not - // a subtype of Array[Int] on the JVM. However, when I attempted - // to remove it I got verify errors when compiling the library - // under -optimize + def <:<(other: TypeKind): Boolean + + /** + * this is directly assignable to other if no coercion or + * casting is needed to convert this to other. It's a distinct + * relationship from <:< because on the JVM, BOOL, BYTE, CHAR, + * SHORT need no coercion to INT even though JVM arrays + * are covariant, ARRAY[SHORT] is not a subtype of ARRAY[INT] + */ + final def isAssignabledTo(other: TypeKind): Boolean = other match { case INT => this.isIntSizedType - case _ => this eq other + case _ => this <:< other } - + /** Is this type a category 2 type in JVM terms? (ie, is it LONG or DOUBLE?) */ def isWideType: Boolean = false @@ -117,6 +120,7 @@ trait TypeKinds { self: ICodes => override def toString = { this.getClass.getName stripSuffix "$" dropWhile (_ != '$') drop 1 } + def <:<(other: TypeKind): Boolean = this eq other } /** @@ -286,7 +290,7 @@ trait TypeKinds { self: ICodes => } /** Checks subtyping relationship. */ - override def <:<(other: TypeKind) = isNothingType || (other match { + def <:<(other: TypeKind) = isNothingType || (other match { case REFERENCE(cls2) => cls.tpe <:< cls2.tpe case ARRAY(_) => cls == NullClass case _ => false @@ -324,7 +328,7 @@ trait TypeKinds { self: ICodes => /** Array subtyping is covariant, as in Java. Necessary for checking * code that interacts with Java. */ - override def <:<(other: TypeKind) = other match { + def <:<(other: TypeKind) = other match { case ARRAY(elem2) => elem <:< elem2 case REFERENCE(AnyRefClass | ObjectClass) => true // TODO: platform dependent! case _ => false @@ -342,7 +346,7 @@ trait TypeKinds { self: ICodes => } /** Checks subtyping relationship. */ - override def <:<(other: TypeKind) = other match { + def <:<(other: TypeKind) = other match { case BOXED(`kind`) => true case REFERENCE(AnyRefClass | ObjectClass) => true // TODO: platform dependent! case _ => false @@ -355,6 +359,7 @@ trait TypeKinds { self: ICodes => */ case object ConcatClass extends TypeKind { override def toString = "ConcatClass" + def <:<(other: TypeKind): Boolean = this eq other /** * Approximate `lub`. The common type of two references is @@ -365,9 +370,6 @@ trait TypeKinds { self: ICodes => case REFERENCE(_) => AnyRefReference case _ => uncomparable(other) } - - /** Checks subtyping relationship. */ - override def <:<(other: TypeKind) = this eq other } ////////////////// Conversions ////////////////////////////// diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 6e99129ee5..703724f003 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -930,7 +930,7 @@ abstract class ICodeReader extends ClassfileParser { locals.get(idx) match { case Some(ls) => - val l = ls find { loc => loc._2 <:< kind } + val l = ls find { loc => loc._2 isAssignabledTo kind } l match { case Some((loc, _)) => loc case None => |