summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-03-10 10:11:28 -0700
committerPaul Phillips <paulp@improving.org>2013-03-10 21:20:50 -0700
commit9c5ea96b1c0fa45037a96e530b6ae71687a292d1 (patch)
tree15dbf04911a2f2b6ec955eb51b0c1c19f6adaea6
parentcb02c96bed1454e1c0702c529366f3c40d6bffd9 (diff)
downloadscala-9c5ea96b1c0fa45037a96e530b6ae71687a292d1.tar.gz
scala-9c5ea96b1c0fa45037a96e530b6ae71687a292d1.tar.bz2
scala-9c5ea96b1c0fa45037a96e530b6ae71687a292d1.zip
Moved some numeric subtyping logic closer to center.
Fixed bug in numeric widening related to continuations, which enabled simplifying isNumericSubType.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala9
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala2
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeComparers.scala31
3 files changed, 25 insertions, 17 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index a110d6d15d..c19d6b7a56 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1124,16 +1124,19 @@ trait Typers extends Adaptations with Tags {
else {
if (mode.inExprModeButNot(FUNmode)) {
pt.dealias match {
- case TypeRef(_, sym, _) =>
+ // The <: Any requirement inhibits attempts to adapt continuation types
+ // to non-continuation types.
+ case TypeRef(_, sym, _) if tree.tpe <:< AnyClass.tpe =>
// note: was if (pt.typeSymbol == UnitClass) but this leads to a potentially
// infinite expansion if pt is constant type ()
- if (sym == UnitClass && tree.tpe <:< AnyClass.tpe) { // (12)
+ if (sym == UnitClass) { // (12)
if (settings.warnValueDiscard.value)
context.unit.warning(tree.pos, "discarded non-Unit value")
return typedPos(tree.pos, mode, pt) {
Block(List(tree), Literal(Constant()))
}
- } else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe.dealiasWiden, pt)) {
+ }
+ else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt)) {
if (settings.warnNumericWiden.value)
context.unit.warning(tree.pos, "implicit numeric widening")
return typedPos(tree.pos, mode, pt) {
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index fe5a5c81e2..bfba81c654 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -1131,7 +1131,7 @@ trait Definitions extends api.StandardDefinitions {
/** Is type's symbol a numeric value class? */
def isNumericValueType(tp: Type): Boolean = tp match {
case TypeRef(_, sym, _) => isNumericValueClass(sym)
- case _ => false
+ case _ => false
}
// todo: reconcile with javaSignature!!!
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
index 2d499cf299..a03ab1610e 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
@@ -5,6 +5,7 @@ package tpe
import scala.collection.{ mutable }
import Flags._
import util.Statistics
+import scala.annotation.tailrec
trait TypeComparers {
self: SymbolTable =>
@@ -583,9 +584,9 @@ trait TypeComparers {
def isWeakSubType(tp1: Type, tp2: Type) =
- tp1.widen.normalize match {
+ tp1.dealiasWiden match {
case TypeRef(_, sym1, _) if isNumericValueClass(sym1) =>
- tp2.deconst.normalize match {
+ tp2.deconst.dealias match {
case TypeRef(_, sym2, _) if isNumericValueClass(sym2) =>
isNumericSubClass(sym1, sym2)
case tv2 @ TypeVar(_, _) =>
@@ -594,7 +595,7 @@ trait TypeComparers {
isSubType(tp1, tp2)
}
case tv1 @ TypeVar(_, _) =>
- tp2.deconst.normalize match {
+ tp2.deconst.dealias match {
case TypeRef(_, sym2, _) if isNumericValueClass(sym2) =>
tv1.registerBound(tp2, isLowerBound = false, isNumericBound = true)
case _ =>
@@ -604,14 +605,18 @@ trait TypeComparers {
isSubType(tp1, tp2)
}
- /** The isNumericValueType tests appear redundant, but without them
- * test/continuations-neg/function3.scala goes into an infinite loop.
- * (Even if the calls are to typeSymbolDirect.)
- */
- def isNumericSubType(tp1: Type, tp2: Type): Boolean = (
- isNumericValueType(tp1.dealiasWiden)
- && isNumericValueType(tp2.dealias)
- && isNumericSubClass(tp1.typeSymbol, tp2.typeSymbol)
- )
-
+ def isNumericSubType(tp1: Type, tp2: Type) = (
+ isNumericSubClass(primitiveBaseClass(tp1.dealiasWiden), primitiveBaseClass(tp2.dealias))
+ )
+
+ /** If the given type has a primitive class among its base classes,
+ * the symbol of that class. Otherwise, NoSymbol.
+ */
+ private def primitiveBaseClass(tp: Type): Symbol = {
+ @tailrec def loop(bases: List[Symbol]): Symbol = bases match {
+ case Nil => NoSymbol
+ case x :: xs => if (isPrimitiveValueClass(x)) x else loop(xs)
+ }
+ loop(tp.baseClasses)
+ }
}