aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeOps.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-01-19 22:26:23 +0100
committerMartin Odersky <odersky@gmail.com>2014-01-19 22:26:23 +0100
commit38b36268d5d29d25cb430c1e275c06ebb1c8f7dd (patch)
tree166d8147aa0a82a698b72716904befc154459462 /src/dotty/tools/dotc/core/TypeOps.scala
parent6eece756db81a62d6114ff8ce8674cc0c69febaa (diff)
downloaddotty-38b36268d5d29d25cb430c1e275c06ebb1c8f7dd.tar.gz
dotty-38b36268d5d29d25cb430c1e275c06ebb1c8f7dd.tar.bz2
dotty-38b36268d5d29d25cb430c1e275c06ebb1c8f7dd.zip
Normalize parent types so that first one always refers to a class, not a trait.
Also: forward type parameter references of newly added to class scope. This is necessary, or the pattern match in test.scala would fail. Need to find out why.
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeOps.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala54
1 files changed, 34 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index c42f0bb36..0411cc613 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -85,18 +85,43 @@ trait TypeOps { this: Context =>
}
}
+ private def enterArgBinding(formal: Symbol, info: Type, cls: ClassSymbol, decls: Scope) = {
+ val typeArgFlag = if (formal is Local) TypeArgument else EmptyFlags
+ val sym = ctx.newSymbol(cls, formal.name, formal.flags & RetainedTypeArgFlags | typeArgFlag, info)
+ cls.enter(sym, decls)
+ }
+
+ /** If we have member definitions
+ *
+ * type argSym v= from
+ * type from v= to
+ *
+ * where the variances of both alias are the same, then enter a new definition
+ *
+ * type argSym v= to
+ *
+ * unless a definition for `argSym` already exists in the current scope.
+ */
+ def forwardRef(argSym: Symbol, from: Symbol, to: TypeBounds, cls: ClassSymbol, decls: Scope) =
+ argSym.info match {
+ case info @ TypeBounds(lo2 @ TypeRef(ThisType(_), name), hi2) =>
+ if (name == from.name &&
+ (lo2 eq hi2) &&
+ info.variance == to.variance &&
+ !decls.lookup(argSym.name).exists) {
+ // println(s"short-circuit ${argSym.name} was: ${argSym.info}, now: $to")
+ enterArgBinding(argSym, to, cls, decls)
+ }
+ case _ =>
+ }
+
+
/** Normalize a list of parent types of class `cls` that may contain refinements
* to a list of typerefs referring to classes, by converting all refinements to member
* definitions in scope `decls`. Can add members to `decls` as a side-effect.
*/
def normalizeToClassRefs(parents: List[Type], cls: ClassSymbol, decls: Scope): List[TypeRef] = {
- def enterArgBinding(formal: Symbol, info: Type) = {
- val typeArgFlag = if (formal is Local) TypeArgument else EmptyFlags
- val sym = ctx.newSymbol(cls, formal.name, formal.flags & RetainedTypeArgFlags | typeArgFlag, info)
- cls.enter(sym, decls)
- }
-
/** If we just entered the type argument binding
*
* type From = To
@@ -117,19 +142,8 @@ trait TypeOps { this: Context =>
case to @ TypeBounds(lo1, hi1) if lo1 eq hi1 =>
for (pref <- prefs)
for (argSym <- pref.decls)
- if (argSym is TypeArgument) {
- argSym.info match {
- case info @ TypeBounds(lo2 @ TypeRef(ThisType(_), name), hi2) =>
- if (name == from.name &&
- (lo2 eq hi2) &&
- info.variance == to.variance &&
- !decls.lookup(argSym.name).exists) {
-// println(s"short-circuit ${argSym.name} was: ${argSym.info}, now: $to")
- enterArgBinding(argSym, to)
- }
- case _ =>
- }
- }
+ if (argSym is TypeArgument)
+ forwardRef(argSym, from, to, cls, decls)
case _ =>
}
@@ -155,7 +169,7 @@ trait TypeOps { this: Context =>
refinements foreachBinding { (name, refinedInfo) =>
assert(decls.lookup(name) == NoSymbol, // DEBUG
s"redefinition of ${decls.lookup(name).debugString} in ${cls.showLocated}")
- enterArgBinding(formals(name), refinedInfo)
+ enterArgBinding(formals(name), refinedInfo, cls, decls)
}
// These two loops cannot be fused because second loop assumes that
// all arguments have been entered in `decls`.