Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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 <:<.
  • Loading branch information...
commit bfd7863406146aa830028ed77f7b0107fc60e5dc 1 parent 4124a09
@JamesIry JamesIry authored
View
2  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)
View
2  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 {
View
32 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 //////////////////////////////
View
2  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 =>
Please sign in to comment.
Something went wrong with that request. Please try again.