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/typer | |
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/typer')
-rw-r--r-- | src/dotty/tools/dotc/typer/Inferencing.scala | 42 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 9 |
2 files changed, 49 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index 9da57ea53..fba2201bf 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -7,6 +7,7 @@ import ast._ import Contexts._, Types._, Flags._, Denotations._, Names._, StdNames._, NameOps._, Symbols._ import Trees._ import Constants._ +import Scopes._ import annotation.unchecked import util.Positions._ import util.{Stats, SimpleMap} @@ -397,6 +398,47 @@ object Inferencing { defn.ObjectClass.typeRef } + /** Ensure that first typeref in a list of parents points to a non-trait class. + * If that's not already the case, add one. + */ + def ensureFirstIsClass(prefs: List[TypeRef])(implicit ctx: Context): List[TypeRef] = { + def isRealClass(sym: Symbol) = sym.isClass && !(sym is Trait) + def realClassParent(tref: TypeRef): TypeRef = + if (isRealClass(tref.symbol)) tref + else tref.info.parents match { + case pref :: _ => if (isRealClass(pref.symbol)) pref else realClassParent(pref) + case nil => defn.ObjectClass.typeRef + } + def improve(clsRef: TypeRef, parent: TypeRef): TypeRef = { + val pclsRef = realClassParent(parent) + if (pclsRef.symbol derivesFrom clsRef.symbol) pclsRef else clsRef + } + prefs match { + case pref :: _ if isRealClass(pref.symbol) => prefs + case _ => (defn.ObjectClass.typeRef /: prefs)(improve) :: prefs + } + } + + /** Forward bindings of all type parameters of `pcls`. That is, if the type parameter + * if instantiated in a parent class, include its type binding in the current class. + */ + def forwardTypeParams(pcls: ClassSymbol, cls: ClassSymbol, decls: Scope)(implicit ctx: Context): Unit = { + for (tparam <- pcls.typeParams) { + val argSym: Symbol = cls.thisType.member(tparam.name).symbol + argSym.info match { + case TypeAlias(TypeRef(ThisType(_), name)) => + val from = cls.thisType.member(name).symbol + from.info match { + case bounds: TypeBounds => + typr.println(s"forward ref $argSym $from $bounds") + ctx.forwardRef(argSym, from, bounds, cls, decls) + case _ => + } + case _ => + } + } + } + /** Check that class does not define */ def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = { val seen = new mutable.HashMap[Name, List[Symbol]] { diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index ece9f51a7..92441d899 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -7,7 +7,7 @@ import ast._ import Trees._, Constants._, StdNames._, Scopes._, Denotations._ import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._ import ast.desugar, ast.desugar._ -import Inferencing.{fullyDefinedType, AnySelectionProto, checkClassTypeWithStablePrefix} +import Inferencing.{fullyDefinedType, AnySelectionProto, checkClassTypeWithStablePrefix, ensureFirstIsClass, forwardTypeParams} import util.Positions._ import util.SourcePosition import collection.mutable @@ -422,10 +422,15 @@ class Namer { typer: Typer => val parentClsRefs = for ((parentRef, constr) <- parentRefs zip parents) yield checkClassTypeWithStablePrefix(parentRef, constr.pos) + val normalizedParentClsRefs = ensureFirstIsClass(parentClsRefs) index(constr) index(rest)(inClassContext(selfInfo)) - denot.info = ClassInfo(cls.owner.thisType, cls, parentClsRefs, decls, selfInfo) + denot.info = ClassInfo(cls.owner.thisType, cls, normalizedParentClsRefs, decls, selfInfo) + if (parentClsRefs ne normalizedParentClsRefs) { + forwardTypeParams(normalizedParentClsRefs.head.symbol.asClass, cls, decls) + typr.println(i"expanded parents of $denot: $normalizedParentClsRefs%, %") + } } } |