diff options
author | Paul Phillips <paulp@improving.org> | 2013-03-10 10:11:28 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-03-10 21:20:50 -0700 |
commit | 9c5ea96b1c0fa45037a96e530b6ae71687a292d1 (patch) | |
tree | 15dbf04911a2f2b6ec955eb51b0c1c19f6adaea6 | |
parent | cb02c96bed1454e1c0702c529366f3c40d6bffd9 (diff) | |
download | scala-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.scala | 9 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Definitions.scala | 2 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/tpe/TypeComparers.scala | 31 |
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) + } } |