summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-03-13 16:09:33 -0700
committerPaul Phillips <paulp@improving.org>2013-03-13 16:18:01 -0700
commit4f17806b1d3b0e6fb66a387b74ee9ea15da77ed8 (patch)
tree1b88dcb05917904d3c4d317763660903c64b6432 /src/reflect
parenta063bb020f2b965b0356491b08c04be0f308872b (diff)
downloadscala-4f17806b1d3b0e6fb66a387b74ee9ea15da77ed8.tar.gz
scala-4f17806b1d3b0e6fb66a387b74ee9ea15da77ed8.tar.bz2
scala-4f17806b1d3b0e6fb66a387b74ee9ea15da77ed8.zip
Eliminated containsNull.
This was a little trickier than the previous. I introduced a new method 'isBottomSubClass' which is the obvious complement to the beloved 'isNonBottomSubClass'. In eliminating the two call sites of containsNull I might have overshot the mark a bit when I rewrote fourthTry and thirdTryRef, but who is going to argue with such beauty as this.
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala13
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala31
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeComparers.scala122
3 files changed, 85 insertions, 81 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 6837f37445..c881de7830 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -1671,6 +1671,19 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* and is this class symbol also different from Null or Nothing? */
def isNonBottomSubClass(that: Symbol): Boolean = false
+ /** Is this class symbol Null or Nothing,
+ * and (if Null) is `that` inhabited by null?
+ * If this is Nothing, of course, it is a
+ * subclass of `that` by definition.
+ *
+ * TODO - what is implied by the fact that AnyVal now has
+ * infinitely many non-bottom subclasses, not only 9?
+ */
+ def isBottomSubClass(that: Symbol) = (
+ (this eq NothingClass)
+ || (this eq NullClass) && that.isClass && (that ne NothingClass) && !(that isNonBottomSubClass AnyValClass)
+ )
+
/** Overridden in NullClass and NothingClass for custom behavior.
*/
def isSubClass(that: Symbol) = isNonBottomSubClass(that)
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 5d2ea1d97f..a678edbe01 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -4051,23 +4051,22 @@ trait Types
corresponds3(tps1, tps2, tparams map (_.variance))(isSubArg)
}
- protected[internal] def containsNull(sym: Symbol): Boolean =
- sym.isClass && sym != NothingClass &&
- !(sym isNonBottomSubClass AnyValClass)
-
- def specializesSym(tp: Type, sym: Symbol, depth: Int): Boolean =
- tp.typeSymbol == NothingClass ||
- tp.typeSymbol == NullClass && containsNull(sym.owner) || {
- def specializedBy(membr: Symbol): Boolean =
- membr == sym || specializesSym(tp.narrow, membr, sym.owner.thisType, sym, depth)
- val member = tp.nonPrivateMember(sym.name)
+ def specializesSym(tp: Type, sym: Symbol, depth: Int): Boolean = {
+ def directlySpecializedBy(member: Symbol): Boolean = (
+ member == sym
+ || specializesSym(tp.narrow, member, sym.owner.thisType, sym, depth)
+ )
+ // Closure reduction, else this would be simply `member exists directlySpecializedBy`
+ def specializedBy(member: Symbol): Boolean = (
if (member eq NoSymbol) false
- else if (member.isOverloaded) member.alternatives exists specializedBy
- else specializedBy(member)
- // was
- // (tp.nonPrivateMember(sym.name).alternatives exists
- // (alt => sym == alt || specializesSym(tp.narrow, alt, sym.owner.thisType, sym, depth)))
- }
+ else if (member.isOverloaded) member.alternatives exists directlySpecializedBy
+ else directlySpecializedBy(member)
+ )
+
+ ( (tp.typeSymbol isBottomSubClass sym.owner)
+ || specializedBy(tp nonPrivateMember sym.name)
+ )
+ }
/** Does member `sym1` of `tp1` have a stronger type
* than member `sym2` of `tp2`?
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
index 863d2109df..d36aa0c927 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
@@ -74,14 +74,17 @@ trait TypeComparers {
// if (subsametypeRecursions == 0) undoLog.clear()
}
- def isDifferentTypeConstructor(tp1: Type, tp2: Type): Boolean = tp1 match {
- case TypeRef(pre1, sym1, _) =>
- tp2 match {
- case TypeRef(pre2, sym2, _) => sym1 != sym2 || isDifferentType(pre1, pre2)
- case _ => true
- }
- case _ => true
- }
+ def isDifferentTypeConstructor(tp1: Type, tp2: Type) = !isSameTypeConstructor(tp1, tp2)
+
+ private def isSameTypeConstructor(tr1: TypeRef, tr2: TypeRef): Boolean = (
+ (tr1.sym == tr2.sym)
+ && !isDifferentType(tr1.pre, tr2.pre)
+ )
+ private def isSameTypeConstructor(tp1: Type, tp2: Type): Boolean = (
+ tp1.isInstanceOf[TypeRef]
+ && tp2.isInstanceOf[TypeRef]
+ && isSameTypeConstructor(tp1.asInstanceOf[TypeRef], tp2.asInstanceOf[TypeRef])
+ )
/** Do `tp1` and `tp2` denote equivalent types? */
def isSameType(tp1: Type, tp2: Type): Boolean = try {
@@ -403,6 +406,9 @@ trait TypeComparers {
case tr2: TypeRef =>
tp1 match {
case tr1: TypeRef =>
+ // TODO - dedicate a method to TypeRef/TypeRef subtyping.
+ // These typerefs are pattern matched up and down far more
+ // than is necessary.
val sym1 = tr1.sym
val sym2 = tr2.sym
val pre1 = tr1.pre
@@ -465,26 +471,19 @@ trait TypeComparers {
def thirdTryRef(tp1: Type, tp2: TypeRef): Boolean = {
val sym2 = tp2.sym
+ def retry(lhs: Type, rhs: Type) = isSubType(lhs, rhs, depth)
+ def abstractTypeOnRight(lo: Type) = isDifferentTypeConstructor(tp2, lo) && retry(tp1, lo)
+ def classOnRight = (
+ if (isRawType(tp2)) retry(tp1, rawToExistential(tp2))
+ else if (sym2.isRefinementClass) retry(tp1, sym2.info)
+ else fourthTry
+ )
sym2 match {
- case SingletonClass => tp1.isStable || fourthTry
- case _: ClassSymbol =>
- if (isRawType(tp2))
- isSubType(tp1, rawToExistential(tp2), depth)
- else if (sym2.name == tpnme.REFINE_CLASS_NAME)
- isSubType(tp1, sym2.info, depth)
- else
- fourthTry
- case _: TypeSymbol =>
- if (sym2 hasFlag DEFERRED) {
- val tp2a = tp2.bounds.lo
- isDifferentTypeConstructor(tp2, tp2a) &&
- isSubType(tp1, tp2a, depth) ||
- fourthTry
- } else {
- isSubType(tp1.normalize, tp2.normalize, depth)
- }
- case _ =>
- fourthTry
+ case SingletonClass => tp1.isStable || fourthTry
+ case _: ClassSymbol => classOnRight
+ case _: TypeSymbol if sym2.isDeferred => abstractTypeOnRight(tp2.bounds.lo) || fourthTry
+ case _: TypeSymbol => retry(tp1.normalize, tp2.normalize)
+ case _ => fourthTry
}
}
@@ -536,44 +535,37 @@ trait TypeComparers {
/** Fourth try, on the left:
* - handle typerefs, refined types, and singleton types.
*/
- def fourthTry = tp1 match {
- case tr1 @ TypeRef(pre1, sym1, _) =>
- sym1 match {
- case NothingClass => true
- case NullClass =>
- tp2 match {
- case TypeRef(_, sym2, _) =>
- containsNull(sym2)
- case _ =>
- isSingleType(tp2) && isSubType(tp1, tp2.widen, depth)
- }
- case _: ClassSymbol =>
- if (isRawType(tp1))
- isSubType(rawToExistential(tp1), tp2, depth)
- else if (sym1.isModuleClass) tp2 match {
- case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1.sourceModule, pre1, sym2, pre2)
- case _ => false
- }
- else if (sym1.isRefinementClass)
- isSubType(sym1.info, tp2, depth)
- else false
-
- case _: TypeSymbol =>
- if (sym1 hasFlag DEFERRED) {
- val tp1a = tp1.bounds.hi
- isDifferentTypeConstructor(tp1, tp1a) && isSubType(tp1a, tp2, depth)
- } else {
- isSubType(tp1.normalize, tp2.normalize, depth)
- }
- case _ =>
- false
- }
- case RefinedType(parents1, _) =>
- parents1 exists (isSubType(_, tp2, depth))
- case _: SingletonType =>
- isSubType(tp1.underlying, tp2, depth)
- case _ =>
- false
+ def fourthTry = {
+ def retry(lhs: Type, rhs: Type) = isSubType(lhs, rhs, depth)
+ def abstractTypeOnLeft(hi: Type) = isDifferentTypeConstructor(tp1, hi) && retry(hi, tp2)
+
+ tp1 match {
+ case tr1 @ TypeRef(pre1, sym1, _) =>
+ def nullOnLeft = tp2 match {
+ case TypeRef(_, sym2, _) => sym1 isBottomSubClass sym2
+ case _ => isSingleType(tp2) && retry(tp1, tp2.widen)
+ }
+ def moduleOnLeft = tp2 match {
+ case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1.sourceModule, pre1, sym2, pre2)
+ case _ => false
+ }
+ def classOnLeft = (
+ if (isRawType(tp1)) retry(rawToExistential(tp1), tp2)
+ else if (sym1.isModuleClass) moduleOnLeft
+ else sym1.isRefinementClass && retry(sym1.info, tp2)
+ )
+ sym1 match {
+ case NothingClass => true
+ case NullClass => nullOnLeft
+ case _: ClassSymbol => classOnLeft
+ case _: TypeSymbol if sym1.isDeferred => abstractTypeOnLeft(tp1.bounds.hi)
+ case _: TypeSymbol => retry(tp1.normalize, tp2.normalize)
+ case _ => false
+ }
+ case RefinedType(parents, _) => parents exists (retry(_, tp2))
+ case _: SingletonType => retry(tp1.underlying, tp2)
+ case _ => false
+ }
}
firstTry