aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-09-26 12:03:10 +0200
committerMartin Odersky <odersky@gmail.com>2013-09-26 12:43:55 +0200
commit54acd26dcf377e2eb2a474399894e10cfd4322f5 (patch)
treea275062a8cab9e81b401a4745400f8db71fed1ae /src/dotty/tools/dotc
parentb7f5aa30383730dc1d2b34f9773695d0f5669bcd (diff)
downloaddotty-54acd26dcf377e2eb2a474399894e10cfd4322f5.tar.gz
dotty-54acd26dcf377e2eb2a474399894e10cfd4322f5.tar.bz2
dotty-54acd26dcf377e2eb2a474399894e10cfd4322f5.zip
Added isRef method to determine whether a type is a typeref that refers to a symbol.
The alternative (tpe eq sym.typeConstructor) does not work because types are not unique. The alternative (tpe.typeSymbol == sym) does not work because other types than TypeRefs have typeSymbols.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala21
-rw-r--r--src/dotty/tools/dotc/core/Types.scala36
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala4
-rw-r--r--src/dotty/tools/dotc/core/transform/Erasure.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala2
-rw-r--r--src/dotty/tools/dotc/typer/EtaExpansion.scala3
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala6
10 files changed, 48 insertions, 34 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index adc268943..665fbec89 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -157,7 +157,7 @@ trait TreeInfo[T >: Untyped] { self: Trees.Instance[T] =>
/** Is tpt a by-name parameter type of the form => T? */
def isByNameParamType(tpt: Tree)(implicit ctx: Context) = tpt match {
- case tpt: TypeTree => tpt.typeOpt.typeSymbol == defn.ByNameParamClass
+ case tpt: TypeTree => tpt.typeOpt isRef defn.ByNameParamClass
case AppliedTypeTree(Select(_, tpnme.BYNAME_PARAM_CLASS), _) => true
case _ => false
}
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index f723dca48..588756db4 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -220,8 +220,8 @@ class TypeComparer(initctx: Context) extends DotClass {
case tp2: RefinedType =>
isSubType(tp1, tp2.parent) && (
tp2.refinedName == nme.WILDCARD
- || (tp1.typeSymbol eq NothingClass)
- || (tp1.typeSymbol eq NullClass)
+ || (tp1 isRef NothingClass)
+ || (tp1 isRef NullClass)
|| tp1.member(tp2.refinedName).hasAltWith(alt =>
isSubType(alt.info, tp2.refinedInfo)))
case AndType(tp21, tp22) =>
@@ -258,8 +258,8 @@ class TypeComparer(initctx: Context) extends DotClass {
case TypeBounds(lo2, hi2) =>
tp1 match {
case TypeBounds(lo1, hi1) =>
- ((lo2.typeSymbol eq NothingClass) || isSubType(lo2, lo1)) &&
- ((hi2.typeSymbol eq AnyClass) || isSubType(hi1, hi2))
+ ((lo2 isRef NothingClass) || isSubType(lo2, lo1)) &&
+ ((hi2 isRef AnyClass) || isSubType(hi1, hi2))
case tp1: ClassInfo =>
val tt = tp1.typeConstructor // was typeTemplate
isSubType(lo2, tt) && isSubType(tt, hi2)
@@ -386,8 +386,9 @@ class TypeComparer(initctx: Context) extends DotClass {
formals2 match {
case formal2 :: rest2 =>
(isSameType(formal1, formal2)
- || isJava1 && formal2.typeSymbol == ObjectClass && formal1.typeSymbol == AnyClass
- || isJava2 && formal1.typeSymbol == ObjectClass && formal2.typeSymbol == AnyClass) && matchingParams(rest1, rest2, isJava1, isJava2)
+ || isJava1 && (formal2 isRef ObjectClass) && (formal1 isRef AnyClass)
+ || isJava2 && (formal1 isRef ObjectClass) && (formal2 isRef AnyClass)) &&
+ matchingParams(rest1, rest2, isJava1, isJava2)
case nil =>
false
}
@@ -402,8 +403,8 @@ class TypeComparer(initctx: Context) extends DotClass {
def glb(tp1: Type, tp2: Type): Type =
if (tp1 eq tp2) tp1
- else if (!tp1.exists || (tp1.typeSymbol eq AnyClass) || (tp2.typeSymbol eq NothingClass)) tp2
- else if (!tp2.exists || (tp2.typeSymbol eq AnyClass) || (tp1.typeSymbol eq NothingClass)) tp1
+ else if (!tp1.exists || (tp1 isRef AnyClass) || (tp2 isRef NothingClass)) tp2
+ else if (!tp2.exists || (tp2 isRef AnyClass) || (tp1 isRef NothingClass)) tp1
else tp2 match { // normalize to disjunctive normal form if possible.
case OrType(tp21, tp22) =>
tp1 & tp21 | tp1 & tp22
@@ -442,8 +443,8 @@ class TypeComparer(initctx: Context) extends DotClass {
def lub(tp1: Type, tp2: Type): Type =
if (tp1 eq tp2) tp1
- else if (!tp1.exists || (tp1.typeSymbol eq AnyClass) || (tp2.typeSymbol eq NothingClass)) tp1
- else if (!tp2.exists || (tp2.typeSymbol eq AnyClass) || (tp1.typeSymbol eq NothingClass)) tp2
+ else if (!tp1.exists || (tp1 isRef AnyClass) || (tp2 isRef NothingClass)) tp1
+ else if (!tp2.exists || (tp2 isRef AnyClass) || (tp1 isRef NothingClass)) tp2
else {
val t1 = mergeIfSuper(tp1, tp2)
if (t1.exists) t1
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index ddb42916e..3e419359b 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -53,7 +53,6 @@ object Types {
* | | +--- ConstantType
* | | +--- MethodParam
* | | +--- RefinedThis
- * | | +--- NoPrefix
* | +- PolyParam
* | +- RefinedType
* | +- TypeBounds
@@ -69,6 +68,7 @@ object Types {
* +- ClassInfo
* |
* +- NoType
+ * +- NoPrefix
* +- ErrorType
* +- WildcardType
*/
@@ -92,16 +92,30 @@ object Types {
case _ => false
}
- /** Is this type an instance of the given class `cls`? */
- final def isClassType(cls: Symbol)(implicit ctx: Context): Boolean =
- dealias.typeSymbol == cls
+ /** Is this type a (possibly aliased and/or partially applied) type reference
+ * to the given type symbol?
+ * @sym The symbol to compare to. It must be a class symbol or abstract type.
+ * It makes no sense for it to be an alias type because isRef would always
+ * return false in that case.
+ */
+ def isRef(sym: Symbol)(implicit ctx: Context): Boolean = stripTypeVar match {
+ case this1: TypeRef =>
+ val thissym = this1.symbol
+ if (thissym.isAliasType) this1.info.bounds.hi.isRef(sym)
+ else thissym eq sym
+ case this1: RefinedType =>
+ // make sure all refinements are type arguments
+ this1.parent.isRef(sym) && this.typeArgs.nonEmpty
+ case _ =>
+ false
+ }
/** Is this type an instance of a non-bottom subclass of the given class `cls`? */
- final def derivesFrom(cls: Symbol)(implicit ctx: Context): Boolean =
+ final def derivesFrom(cls: Symbol)(implicit defctx: Context): Boolean =
classSymbol.derivesFrom(cls)
/** Is this an array type? */
- final def isArray(implicit ctx: Context): Boolean = isClassType(defn.ArrayClass)
+ final def isArray(implicit ctx: Context): Boolean = isRef(defn.ArrayClass)
/** A type T is a legal prefix in a type selection T#A if
* T is stable or T contains no uninstantiated type variables.
@@ -568,7 +582,7 @@ object Types {
/** Map references to Object to references to Any; needed for Java interop */
final def objToAny(implicit ctx: Context) =
- if (isClassType(defn.ObjectClass) && !ctx.phase.erasedTypes) defn.AnyType else this
+ if ((this isRef defn.ObjectClass) && !ctx.phase.erasedTypes) defn.AnyType else this
/** If this is repeated parameter type, its underlying type,
* else the type itself.
@@ -837,8 +851,8 @@ object Types {
final def argType(tparam: Symbol)(implicit ctx: Context): Type = this match {
case TypeBounds(lo, hi) =>
val v = tparam.variance
- if (v > 0 && lo.isClassType(defn.NothingClass)) hi
- else if (v < 0 && hi.isClassType(defn.AnyClass)) lo
+ if (v > 0 && (lo isRef defn.NothingClass)) hi
+ else if (v < 0 && (hi isRef defn.AnyClass)) lo
else if (v == 0 && (lo eq hi)) lo
else NoType
case _ =>
@@ -1867,9 +1881,9 @@ object Types {
if ((prefix eq cls.owner.thisType) || !cls.owner.isClass) tp
else tp.substThis(cls.owner.asClass, prefix)
- private var tyconCache: Type = null
+ private var tyconCache: TypeRef = null
- def typeConstructor(implicit ctx: Context): Type = {
+ def typeConstructor(implicit ctx: Context): TypeRef = {
def clsDenot = if (prefix eq cls.owner.thisType) cls.denot else cls.denot.copySymDenotation(info = this)
if (tyconCache == null)
tyconCache =
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index fc3fb49ec..f640c3d67 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -248,7 +248,7 @@ class ClassfileParser(
val tp = sig2type(tparams, skiptvs)
// sig2type seems to return AnyClass regardless of the situation:
// we don't want Any as a LOWER bound.
- if (tp.typeSymbol == defn.AnyClass) TypeBounds.empty
+ if (tp isRef defn.AnyClass) TypeBounds.empty
else TypeBounds.lower(tp)
case '*' => TypeBounds.empty
}
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 109987dcf..4570d0654 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -71,7 +71,7 @@ object UnPickler {
assert(lastArg.isArray)
val elemtp0 :: Nil = lastArg.baseTypeArgs(defn.ArrayClass)
val elemtp = elemtp0 match {
- case AndType(t1, t2) if t1.typeSymbol.isAbstractType && t2.isClassType(defn.ObjectClass) =>
+ case AndType(t1, t2) if t1.typeSymbol.isAbstractType && (t2 isRef defn.ObjectClass) =>
t1 // drop intersection with Object for abstract types in varargs. UnCurry can handle them.
case _ =>
elemtp0
@@ -538,7 +538,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
*/
def elimExistentials(boundSyms: List[Symbol], tp: Type): Type = {
def removeSingleton(tp: Type): Type =
- if (tp.isClassType(defn.SingletonClass)) defn.AnyType else tp
+ if (tp isRef defn.SingletonClass) defn.AnyType else tp
def elim(tp: Type): Type = tp match {
case tp @ RefinedType(parent, name) =>
val parent1 = elim(tp.parent)
diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala
index 6bb07e699..201dd107f 100644
--- a/src/dotty/tools/dotc/core/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/core/transform/Erasure.scala
@@ -131,10 +131,10 @@ object Erasure {
}
def resultErasure(tp: Type)(implicit ctx: Context) =
- if (tp.isClassType(defn.UnitClass)) tp else erasure(tp)
+ if (tp isRef defn.UnitClass) tp else erasure(tp)
def removeLaterObjects(trs: List[TypeRef])(implicit ctx: Context): List[TypeRef] = trs match {
- case tr :: trs1 => tr :: trs1.filterNot(_.isClassType(defn.ObjectClass))
+ case tr :: trs1 => tr :: trs1.filterNot(_ isRef defn.ObjectClass)
case nil => nil
}
}
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index f81fcf3cd..bf49091ec 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -556,7 +556,7 @@ trait Applications extends Compatibility { self: Typer =>
if (tp derivesFrom defn.ProductClass) productSelectors
else if (tp derivesFrom defn.SeqClass) seqSelector :: Nil
- else if (tp.typeSymbol == defn.BooleanClass) Nil
+ else if (tp isRef defn.BooleanClass) Nil
else if (extractorMemberType(nme.isDefined).exists &&
extractorMemberType(nme.get).exists) recur(extractorMemberType(nme.get))
else {
diff --git a/src/dotty/tools/dotc/typer/EtaExpansion.scala b/src/dotty/tools/dotc/typer/EtaExpansion.scala
index 6a2b2060e..155574c81 100644
--- a/src/dotty/tools/dotc/typer/EtaExpansion.scala
+++ b/src/dotty/tools/dotc/typer/EtaExpansion.scala
@@ -31,11 +31,10 @@ object EtaExpansion {
def liftArgs(defs: mutable.ListBuffer[Tree], methType: Type, args: List[Tree])(implicit ctx: Context) = {
def toPrefix(name: Name) = if (name contains '$') "" else name.toString
- def isByName(tp: Type) = tp.typeSymbol == defn.ByNameParamClass
val paramInfos = methType match {
case MethodType(paramNames, paramTypes) =>
(paramNames, paramTypes).zipped map ((name, tp) =>
- (toPrefix(name), isByName(tp)))
+ (toPrefix(name), tp isRef defn.ByNameParamClass))
case _ =>
args map Function.const(("", false))
}
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 7a8b94571..2137981e7 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -28,7 +28,7 @@ object Inferencing {
*/
def isCompatible(tp: Type, pt: Type)(implicit ctx: Context): Boolean = (
(tp <:< pt)
- || pt.typeSymbol == defn.ByNameParamClass && (tp <:< pt.typeArgs.head)
+ || (pt isRef defn.ByNameParamClass) && (tp <:< pt.typeArgs.head)
|| viewExists(tp, pt))
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 69b79a474..0c33aa026 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -387,7 +387,7 @@ class Typer extends Namer with Applications with Implicits {
def typedPair(tree: untpd.Pair, pt: Type)(implicit ctx: Context) = {
val (leftProto, rightProto) = pt.typeArgs match {
- case l :: r :: Nil if pt.typeSymbol == defn.PairClass => (l, r)
+ case l :: r :: Nil if pt isRef defn.PairClass => (l, r)
case _ => (WildcardType, WildcardType)
}
val left1 = typed(tree.left, leftProto)
@@ -468,7 +468,7 @@ class Typer extends Namer with Applications with Implicits {
else {
val params = args.asInstanceOf[List[ValDef]]
val protoFormals: List[Type] = pt match {
- case _ if pt.typeSymbol == defn.FunctionClass(params.length) =>
+ case _ if pt isRef defn.FunctionClass(params.length) =>
pt.typeArgs take params.length
case SAMType(meth) =>
val MethodType(_, paramTypes) = meth.info
@@ -1028,7 +1028,7 @@ class Typer extends Namer with Applications with Implicits {
val folded = ConstFold(tree, pt)
if (folded ne EmptyTree) return folded
// drop type if prototype is Unit
- if (pt.typeSymbol == defn.UnitClass)
+ if (pt isRef defn.UnitClass)
return tpd.Block(tree :: Nil, Literal(Constant()))
// convert function literal to SAM closure
tree match {