summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-03-31 12:14:43 -0700
committerPaul Phillips <paulp@improving.org>2012-04-01 08:27:08 -0700
commit4f24d01d226608aaf6d92cc20659f59e5d29b299 (patch)
treeaa7a18231cd33bb30f81289d814966dfc44516d6 /src/compiler
parent03aca2c5bc293f8fd79e99b2aaac79cdc043c1da (diff)
downloadscala-4f24d01d226608aaf6d92cc20659f59e5d29b299.tar.gz
scala-4f24d01d226608aaf6d92cc20659f59e5d29b299.tar.bz2
scala-4f24d01d226608aaf6d92cc20659f59e5d29b299.zip
Cleaned up "isTupleTypeOrSubtype".
More principled logic for determining if a type is a particular type or a specialized subtype of that type.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala56
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala11
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala12
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala10
6 files changed, 53 insertions, 41 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 09c2228b01..0188fb3944 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -524,26 +524,48 @@ trait Definitions extends reflect.api.StandardDefinitions {
else nme.genericWrapArray
}
+ @deprecated("Use isTupleType", "2.10.0")
+ def isTupleTypeOrSubtype(tp: Type): Boolean = isTupleType(tp)
+
def tupleField(n: Int, j: Int) = getMember(TupleClass(n), nme.productAccessorName(j))
- def isTupleType(tp: Type): Boolean = isTupleType(tp, false)
- def isTupleTypeOrSubtype(tp: Type): Boolean = isTupleType(tp, true)
- private def isTupleType(tp: Type, subtypeOK: Boolean) = tp.normalize match {
- case TypeRef(_, sym, args) if args.nonEmpty =>
- val len = args.length
- len <= MaxTupleArity && {
- val tsym = TupleClass(len)
- (sym == tsym) || (subtypeOK && !tp.isHigherKinded && sym.isSubClass(tsym))
- }
- case _ => false
+ def isTupleSymbol(sym: Symbol) = TupleClass contains unspecializedSymbol(sym)
+
+ def unspecializedSymbol(sym: Symbol): Symbol = {
+ if (sym hasFlag SPECIALIZED) {
+ // add initialization from its generic class constructor
+ val genericName = nme.unspecializedName(sym.name)
+ val member = sym.owner.info.decl(genericName.toTypeName)
+ member
}
+ else sym
+ }
- def tupleType(elems: List[Type]) = {
- val len = elems.length
- if (len <= MaxTupleArity) {
- val sym = TupleClass(len)
- typeRef(sym.typeConstructor.prefix, sym, elems)
- } else NoType
- }
+ // Checks whether the given type is true for the given condition,
+ // or if it is a specialized subtype of a type for which it is true.
+ def isPossiblySpecializedType(tp: Type)(cond: Type => Boolean) = {
+ cond(tp) || (tp match {
+ case TypeRef(pre, sym, args) if sym hasFlag SPECIALIZED =>
+ cond(tp baseType unspecializedSymbol(sym))
+ case _ =>
+ false
+ })
+ }
+ // No normalization.
+ def isTupleTypeDirect(tp: Type) = isPossiblySpecializedType(tp) {
+ case TypeRef(_, sym, args) if args.nonEmpty =>
+ val len = args.length
+ len <= MaxTupleArity && sym == TupleClass(len)
+ case _ => false
+ }
+ def isTupleType(tp: Type) = isTupleTypeDirect(tp.normalize)
+
+ def tupleType(elems: List[Type]) = {
+ val len = elems.length
+ if (len <= MaxTupleArity) {
+ val sym = TupleClass(len)
+ typeRef(sym.typeConstructor.prefix, sym, elems)
+ } else NoType
+ }
lazy val ProductRootClass: Symbol = getRequiredClass("scala.Product")
def Product_productArity = getMember(ProductRootClass, nme.productArity)
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index bb9549deba..f70e9760f7 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -2174,13 +2174,14 @@ trait Types extends api.Types { self: SymbolTable =>
case TypeRef(_, RepeatedParamClass, arg :: _) => arg + "*"
case TypeRef(_, ByNameParamClass, arg :: _) => "=> " + arg
case _ =>
+ def targs = normalize.typeArgs
+
if (isFunctionType(this)) {
- val targs = normalize.typeArgs
// Aesthetics: printing Function1 as T => R rather than (T) => R
// ...but only if it's not a tuple, so ((T1, T2)) => R is distinguishable
// from (T1, T2) => R.
targs match {
- case in :: out :: Nil if !isTupleTypeOrSubtype(in) =>
+ case in :: out :: Nil if !isTupleType(in) =>
// A => B => C should be (A => B) => C or A => (B => C)
val in_s = if (isFunctionType(in)) "(" + in + ")" else "" + in
val out_s = if (isFunctionType(out)) "(" + out + ")" else "" + out
@@ -2189,9 +2190,9 @@ trait Types extends api.Types { self: SymbolTable =>
xs.init.mkString("(", ", ", ")") + " => " + xs.last
}
}
- else if (isTupleTypeOrSubtype(this))
- normalize.typeArgs.mkString("(", ", ", if (hasLength(normalize.typeArgs, 1)) ",)" else ")")
- else if (sym.isAliasType && prefixChain.exists(_.termSymbol.isSynthetic) && (normalize ne this))
+ else if (isTupleType(this))
+ targs.mkString("(", ", ", if (hasLength(targs, 1)) ",)" else ")")
+ else if (sym.isAliasType && prefixChain.exists(_.termSymbol.isSynthetic) && (this ne this.normalize))
"" + normalize
else
""
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index dd1c75c322..702d643fb4 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -620,7 +620,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
case tp: TypeRef if definitions.isByNameParamType(tp) =>
nameBuffer append "⇒ "
appendType0(tp.args.head)
- case tp: TypeRef if definitions.isTupleTypeOrSubtype(tp) =>
+ case tp: TypeRef if definitions.isTupleType(tp) =>
val args = tp.normalize.typeArgs
nameBuffer append '('
appendTypes0(args, ", ")
diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
index 015dc2a7f1..808f549304 100644
--- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
@@ -15,7 +15,7 @@ trait CompletionOutput {
val global: Global
import global._
- import definitions.{ isTupleTypeOrSubtype, isFunctionType, isRepeatedParamType }
+ import definitions.{ isTupleType, isFunctionType, isRepeatedParamType }
/** Reducing fully qualified noise for some common packages.
*/
@@ -48,11 +48,11 @@ trait CompletionOutput {
def typeToString(tp: Type): String = relativize(
tp match {
- case x if isFunctionType(x) => functionString(x)
- case x if isTupleTypeOrSubtype(x) => tupleString(x)
- case x if isRepeatedParamType(x) => typeToString(x.typeArgs.head) + "*"
- case mt @ MethodType(_, _) => methodTypeToString(mt)
- case x => x.toString
+ case x if isFunctionType(x) => functionString(x)
+ case x if isTupleType(x) => tupleString(x)
+ case x if isRepeatedParamType(x) => typeToString(x.typeArgs.head) + "*"
+ case mt @ MethodType(_, _) => methodTypeToString(mt)
+ case x => x.toString
}
)
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index 8bdf83fda4..4f6a4c8dc0 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -343,10 +343,9 @@ trait Patterns extends ast.TreeDSL {
def apply(x: Apply): Pattern = {
val Apply(fn, args) = x
def isModule = x.symbol.isModule || x.tpe.termSymbol.isModule
- def isTuple = isTupleTypeOrSubtype(fn.tpe)
if (fn.isType) {
- if (isTuple) TuplePattern(x)
+ if (isTupleType(fn.tpe)) TuplePattern(x)
else ConstructorPattern(x)
}
else if (args.isEmpty) {
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 185cf4f533..1afa1dbf58 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -134,16 +134,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case _ => false
}
- def unspecializedSymbol(sym: Symbol): Symbol = {
- if (sym hasFlag SPECIALIZED) {
- // add initialization from its generic class constructor
- val genericName = nme.unspecializedName(sym.name)
- val member = sym.owner.info.decl(genericName.toTypeName)
- member
- }
- else NoSymbol
- }
-
object TypeEnv {
/** Return a new type environment binding specialized type parameters of sym to
* the given args. Expects the lists to have the same length.