summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-07-23 14:19:45 +0000
committerMartin Odersky <odersky@gmail.com>2008-07-23 14:19:45 +0000
commit34572d6e7aa24b93a0dba89e214ec2869b44d68c (patch)
tree0f48e83fbf949da23edbfd457d21e25aa435e048 /src/compiler/scala/tools/nsc
parent80f341ff128b066edbe5966a26276aa9323b983b (diff)
downloadscala-34572d6e7aa24b93a0dba89e214ec2869b44d68c.tar.gz
scala-34572d6e7aa24b93a0dba89e214ec2869b44d68c.tar.bz2
scala-34572d6e7aa24b93a0dba89e214ec2869b44d68c.zip
(1) made base type sequences lazy in their argu...
(1) made base type sequences lazy in their arguments. Made `validateType' in RefChecks more lenient. First shot at allowing higher-kinded intersection types.
Diffstat (limited to 'src/compiler/scala/tools/nsc')
-rwxr-xr-xsrc/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala113
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala33
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala43
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala5
4 files changed, 120 insertions, 74 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
index e7d5a3daa2..8bc68d8ff1 100755
--- a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
+++ b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
@@ -26,35 +26,48 @@ trait BaseTypeSeqs {
self: SymbolTable =>
import definitions._
- class BaseTypeSeq(elems: Array[Type]) {
+ class BaseTypeSeq(parents: List[Type], elems: Array[Type]) {
/** The number of types in the sequence */
def length: Int = elems.length
/** The type at i'th position in this sequence; lazy types are returned evaluated. */
- def apply(i: Int): Type = elems(i) /*
-match {
- case RefinedType(variants, decls) =>
+ def apply(i: Int): Type = elems(i) match {
+ case NoType =>
+ elems(i) = AnyClass.tpe
+ throw CyclicInheritance
+ case rtp @ RefinedType(variants, decls) =>
// can't assert decls.isEmpty; see t0764
//if (!decls.isEmpty) assert(false, "computing closure of "+this+":"+this.isInstanceOf[RefinedType]+"/"+closureCache(j))
//Console.println("compute closure of "+this+" => glb("+variants+")")
- mergePrefixAndArgs(variants, -1, maxBaseTypeSeqDepth(variants) + LubGlbMargin) match {
- case Some(tp0) =>
- elems(i) = tp0
- tp0
- case None => throw new TypeError(
- "the type intersection "+(parents mkString " with ")+" is malformed"+
- "\n --- because ---"+
- "\n no common type instance of base types "+(variants mkString ", and ")+" exists.")
+ elems(i) = NoType
+ try {
+ mergePrefixAndArgs(variants, -1, maxBaseTypeSeqDepth(variants) + LubGlbMargin) match {
+ case Some(tp0) =>
+ elems(i) = tp0
+ tp0
+ case None =>
+ typeError(
+ "no common type instance of base types "+(variants mkString ", and ")+" exists.")
+ }
+ } catch {
+ case CyclicInheritance =>
+ typeError(
+ "computing the common type instance of base types "+(variants mkString ", and ")+" leads to a cycle.")
}
case tp =>
tp
- }*/
+ }
+
+ def rawElem(i: Int) = elems(i)
/** The type symbol of the type at i'th position in this sequence;
* no evaluation needed.
*/
- def typeSymbol(i: Int): Symbol = elems(i).typeSymbol
+ def typeSymbol(i: Int): Symbol = elems(i) match {
+ case RefinedType(v :: vs, _) => v.typeSymbol
+ case tp => tp.typeSymbol
+ }
/** Return all evaluated types in this sequence as a list */
def toList: List[Type] = elems.toList
@@ -63,7 +76,7 @@ match {
val arr = new Array[Type](elems.length + offset)
Array.copy(elems, 0, arr, offset, elems.length)
arr(0) = head
- new BaseTypeSeq(arr)
+ new BaseTypeSeq(parents, arr)
}
/** Compute new base type sequence with `tp' prepended to this sequence */
@@ -74,12 +87,12 @@ match {
/** Compute new base type sequence where every element is mapped
* with function `f'. Lazy types are mapped but not evaluated */
- def map(f: Type => Type): BaseTypeSeq = new BaseTypeSeq(elems map f)
+ def map(f: Type => Type): BaseTypeSeq = new BaseTypeSeq(parents, elems map f)
def exists(p: Type => Boolean): Boolean = elems exists p
// (0 until length) exists (i => p(this(i)))
- def normalize(parents: List[Type]) {
+ def normalize(parents: List[Type]) {}
/*
var j = 0
while (j < elems.length) {
@@ -99,28 +112,32 @@ match {
}
j += 1
}
-*/
}
-
+*/
lazy val maxDepth: Int = {
var d = 0
- for (i <- 0 until length) d = Math.max(d, self.maxDepth(this(i)))
+ for (i <- 0 until length) d = Math.max(d, self.maxDepth(elems(i)))
d
}
override def toString = elems.mkString("BTS(", ",", ")")
+
+ private def typeError(msg: String): Nothing =
+ throw new TypeError(
+ "the type intersection "+(parents mkString " with ")+" is malformed"+
+ "\n --- because ---\n"+msg)
}
/** A merker object for a base type sequence that's no yet computed.
* used to catch inheritance cycles
*/
- val undetBaseTypeSeq: BaseTypeSeq = new BaseTypeSeq(Array())
+ val undetBaseTypeSeq: BaseTypeSeq = new BaseTypeSeq(List(), Array())
/** Create a base type sequence consisting of a single type */
- def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = new BaseTypeSeq(Array(tp))
+ def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = new BaseTypeSeq(List(), Array(tp))
/** Create the base type sequence of a compound type wuth given tp.parents */
- def compoundBaseTypeSeq(tp: CompoundType): BaseTypeSeq = {
+ def compoundBaseTypeSeq(tp: Type/*tsym: Symbol, parents: List[Type]*/): BaseTypeSeq = {
val tsym = tp.typeSymbol
val parents = tp.parents
// Console.println("computing baseTypeSeq of " + tsym.tpe + " " + parents)//DEBUG
@@ -139,26 +156,37 @@ match {
index(i) = 0
i += 1
}
- def nextBaseType(i: Int): Type = {
+ def nextTypeSymbol(i: Int): Symbol = {
val j = index(i)
val pbts = pbtss(i)
- if (j < pbts.length) pbts(j) else AnyClass.tpe
+ if (j < pbts.length) pbts.typeSymbol(j) else AnyClass
+ }
+ def nextRawElem(i: Int): Type = {
+ val j = index(i)
+ val pbts = pbtss(i)
+ if (j < pbts.length) pbts.rawElem(j) else AnyClass.tpe
}
var minSym: Symbol = NoSymbol
while (minSym != AnyClass) {
- minSym = nextBaseType(0).typeSymbol
+ minSym = nextTypeSymbol(0)
i = 1
while (i < nparents) {
- if (nextBaseType(i).typeSymbol isLess minSym)
- minSym = nextBaseType(i).typeSymbol
+ val nextSym = nextTypeSymbol(i)
+ if (nextSym isLess minSym)
+ minSym = nextSym
i += 1
}
var minTypes: List[Type] = List()
i = 0
while (i < nparents) {
- val tp = nextBaseType(i)
- if (tp.typeSymbol == minSym) {
- if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes;
+ if (nextTypeSymbol(i) == minSym) {
+ nextRawElem(i) match {
+ case RefinedType(variants, decls) =>
+ for (tp <- variants)
+ if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes
+ case tp =>
+ if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes
+ }
index(i) = index(i) + 1
}
i += 1
@@ -170,25 +198,8 @@ match {
val elems = new Array[Type](btsSize)
buf.copyToArray(elems, 0)
// Console.println("computed baseTypeSeq of " + tsym.tpe + " " + parents + ": "+elems.toString)//DEBUG
- tp.baseTypeSeqCache = new BaseTypeSeq(elems)
- var j = 0
- while (j < btsSize) {
- elems(j) match {
- case RefinedType(variants, decls) =>
- // can't assert decls.isEmpty; see t0764
- //if (!decls.isEmpty) assert(false, "computing closure of "+this+":"+this.isInstanceOf[RefinedType]+"/"+closureCache(j))
- //Console.println("compute closure of "+this+" => glb("+variants+")")
- elems(j) = mergePrefixAndArgs(variants, -1, maxBaseTypeSeqDepth(variants) + LubGlbMargin) match {
- case Some(tp0) => tp0
- case None => throw new TypeError(
- "the type intersection "+(parents mkString " with ")+" is malformed"+
- "\n --- because ---"+
- "\n no common type instance of base types "+(variants mkString ", and ")+" exists.")
- }
- case _ =>
- }
- j += 1
- }
- tp.baseTypeSeqCache
+ new BaseTypeSeq(parents, elems)
}
+
+ val CyclicInheritance = new Throwable
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 2a83cb3351..26394bac04 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1127,7 +1127,34 @@ trait Types {
*/
case class RefinedType(override val parents: List[Type],
override val decls: Scope) extends CompoundType {
- def isHigherkinded = !parents.isEmpty && (parents forall (_.isHigherKinded)) // MO to AM: please check
+
+ override def isHigherKinded =
+ !parents.isEmpty && (parents forall (_.isHigherKinded)) // @MO to AM: please check this class!
+
+ override def typeParams =
+ if (isHigherKinded) parents.head.typeParams
+ else super.typeParams
+
+ private def higherKindedArgs =
+ typeParams map (_.typeConstructor)
+
+ /* MO to AM: This is probably not correct
+ * If they are several higher-kinded parents with different bounds we need
+ * to take the intersection of their bounds
+ */
+ override def normalize =
+ if (isHigherKinded)
+ PolyType(
+ typeParams,
+ refinementOfClass(
+ typeSymbol,
+ parents map {
+ case TypeRef(pre, sym, List()) => TypeRef(pre, sym, higherKindedArgs)
+ case p => p
+ },
+ decls))
+ else super.normalize
+
override def kind = "RefinedType"
}
@@ -1423,7 +1450,7 @@ A type's typeSymbol should never be inspected directly.
// @M: initialize needed (see test/files/pos/ticket0137.scala)
PolyType(typeParams, typeRef(pre, sym.initialize, higherKindedArgs))
} else if (sym.isRefinementClass) {
- sym.info
+ sym.info.normalize // @MO to AM: OK?
} else {
super.normalize
}
@@ -4230,7 +4257,7 @@ A type's typeSymbol should never be inspected directly.
* `arg2' and print trace of computation.
*/
private def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = {
- Console.println(indent + tp1 + " " + op + " " + arg2 + "?")
+ Console.println(indent + tp1 + " " + op + " " + arg2 + "?" /* + "("+tp1.getClass+","+arg2.asInstanceOf[AnyRef].getClass+")"*/)
indent = indent + " "
val result = p(tp1, arg2)
indent = indent.substring(0, indent.length() - 2)
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 60abdcdb4b..27f7681a98 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -328,38 +328,41 @@ abstract class RefChecks extends InfoTransform {
* Check that later type instances in the base-type sequence
* are subtypes of earlier type instances of the same mixin.
* </li>
- * <li> <!-- 2 -->
- * Check that inner classes do not inherit from Annotation
- * </li>
* </ol>
*/
private def validateBaseTypes(clazz: Symbol) {
- val seenTypes = new Array[Type](clazz.info.baseTypeSeq.length)
+ val seenTypes = new Array[List[Type]](clazz.info.baseTypeSeq.length)
+ for (i <- 0 until seenTypes.length) seenTypes(i) = Nil
/** validate all base types of a class in reverse linear order. */
- def validateType(tp: Type) {
+ def register(tp: Type) {
+// if (clazz.fullNameString.endsWith("Collection.Projection"))
+// println("validate base type "+tp)
val baseClass = tp.typeSymbol
if (baseClass.isClass) {
val index = clazz.info.baseTypeIndex(baseClass)
if (index >= 0) {
- if (seenTypes(index) ne null) {
- if (!(seenTypes(index) <:< tp)) {
- unit.error(clazz.pos, "illegal inheritance;\n " + clazz +
- " inherits different type instances of " + baseClass +
- ":\n" + tp + " and " + seenTypes(index));
- }
- } else {
- seenTypes(index) = tp
- // check that inner classes do not inherit from Annotation
- if (baseClass == ClassfileAnnotationClass)
- if (!clazz.owner.isPackageClass)
- unit.error(clazz.pos, "inner classes cannot be classfile annotations")
- }
- tp.parents.reverse foreach validateType
+ if (seenTypes(index) forall (tp1 => !(tp1 <:< tp)))
+ seenTypes(index) =
+ tp :: (seenTypes(index) filter (tp1 => !(tp <:< tp1)))
}
}
+ tp.parents foreach register
+ }
+ register(clazz.tpe)
+ for (i <- 0 until seenTypes.length) {
+ val baseClass = clazz.info.baseTypeSeq(i).typeSymbol
+ seenTypes(i) match {
+ case List() =>
+ println("??? base "+baseClass+" not found in basetypes of "+clazz)
+ case List(_) =>
+ ;// OK
+ case tp1 :: tp2 :: _ =>
+ unit.error(clazz.pos, "illegal inheritance;\n " + clazz +
+ " inherits different type instances of " + baseClass +
+ ":\n" + tp1 + " and " + tp2);
+ }
}
- validateType(clazz.tpe)
}
// Variance Checking --------------------------------------------------------
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 257461a9cb..6974684ac2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1147,6 +1147,9 @@ trait Typers { self: Analyzer =>
/**
* @param templ ...
* @param parents1 ...
+ * <li> <!-- 2 -->
+ * Check that inner classes do not inherit from Annotation
+ * </li>
* @return ...
*/
def typedTemplate(templ: Template, parents1: List[Tree]): Template = {
@@ -1167,6 +1170,8 @@ trait Typers { self: Analyzer =>
assert(clazz.info.decls != EmptyScope)
enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templ.body)
validateParentClasses(parents1, selfType)
+ if ((clazz isSubClass ClassfileAnnotationClass) && !clazz.owner.isPackageClass)
+ unit.error(clazz.pos, "inner classes cannot be classfile annotations")
if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members
checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType])
val body =