diff options
author | Martin Odersky <odersky@gmail.com> | 2014-01-19 22:26:23 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-01-19 22:26:23 +0100 |
commit | 38b36268d5d29d25cb430c1e275c06ebb1c8f7dd (patch) | |
tree | 166d8147aa0a82a698b72716904befc154459462 /src/dotty/tools/dotc/core/TypeOps.scala | |
parent | 6eece756db81a62d6114ff8ce8674cc0c69febaa (diff) | |
download | dotty-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.scala | 54 |
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`. |