diff options
author | Martin Odersky <odersky@gmail.com> | 2016-06-29 20:12:25 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-07-11 13:35:04 +0200 |
commit | 1e48758ad5c100a7dd4d1a5b846ef5ff37e37721 (patch) | |
tree | fd5e516a574cd392002995f9ea17e2ee9d4ed801 /src/dotty/tools/dotc/typer/Namer.scala | |
parent | 65c26bacbba91850922cfffabfbc6847102bc489 (diff) | |
download | dotty-1e48758ad5c100a7dd4d1a5b846ef5ff37e37721.tar.gz dotty-1e48758ad5c100a7dd4d1a5b846ef5ff37e37721.tar.bz2 dotty-1e48758ad5c100a7dd4d1a5b846ef5ff37e37721.zip |
Refactor handling of unpickled type params
Under the new hk scheme we discovered that type parameters
are sometimes unpickled in the wrong order. The fault was always
present but the previous hk schemes were somehow lenient
enough in their subtyping rules to not discover the problem.
E.g., when reading Coder.scala, dotc believed that parameter
`A` of `TraversableOnce#BufferedCanBuildFrom` is higher-kinded
and parameter `CC` is first-order where the opposite is true.
This commit hardens the way we read type parameters in order
to make this swap impossible by design.
- Revert auto-healing in derivedAppliedType
The healing hid a real error about order of type parameters
in Scala2 unpickling which was fixed in the previous commits.
The healing caused Map.scala to fail because it is possible
that type parameters are mis-prediced to be Nil in an F-bounded
context.
- Smallish fixes to type applications
Diffstat (limited to 'src/dotty/tools/dotc/typer/Namer.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 57 |
1 files changed, 30 insertions, 27 deletions
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index bf36942e0..3b193d2db 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -307,9 +307,14 @@ class Namer { typer: Typer => // have no implementation. val cctx = if (tree.name == nme.CONSTRUCTOR && !(tree.mods is JavaDefined)) ctx.outer else ctx + val completer = tree match { + case tree: TypeDef => new TypeDefCompleter(tree)(cctx) + case _ => new Completer(tree)(cctx) + } + recordSym(ctx.newSymbol( ctx.owner, name, flags | deferred | method | higherKinded | inSuperCall1, - adjustIfModule(new Completer(tree)(cctx), tree), + adjustIfModule(completer, tree), privateWithinClass(tree.mods), tree.pos), tree) case tree: Import => recordSym(ctx.newSymbol( @@ -489,32 +494,11 @@ class Namer { typer: Typer => } /** The completer of a symbol defined by a member def or import (except ClassSymbols) */ - class Completer(val original: Tree)(implicit ctx: Context) extends TypeParamsCompleter { + class Completer(val original: Tree)(implicit ctx: Context) extends LazyType { protected def localContext(owner: Symbol) = ctx.fresh.setOwner(owner).setTree(original) - private var myTypeParams: List[TypeSymbol] = null - private var nestedCtx: Context = null - - def completerTypeParams(sym: Symbol): List[TypeSymbol] = { - if (myTypeParams == null) { - //println(i"completing type params of $sym in ${sym.owner}") - myTypeParams = original match { - case tdef: TypeDef => - nestedCtx = localContext(sym).setNewScope - locally { - implicit val ctx: Context = nestedCtx - completeParams(tdef.tparams) - tdef.tparams.map(symbolOfTree(_).asType) - } - case _ => - Nil - } - } - myTypeParams - } - - private def typeSig(sym: Symbol): Type = original match { + protected def typeSig(sym: Symbol): Type = original match { case original: ValDef => if (sym is Module) moduleValSig(sym) else valOrDefDefSig(original, sym, Nil, Nil, identity)(localContext(sym).setNewScope) @@ -522,9 +506,6 @@ class Namer { typer: Typer => val typer1 = ctx.typer.newLikeThis nestedTyper(sym) = typer1 typer1.defDefSig(original, sym)(localContext(sym).setTyper(typer1)) - case original: TypeDef => - assert(!original.isClassDef) - typeDefSig(original, sym, completerTypeParams(sym))(nestedCtx) case imp: Import => try { val expr1 = typedAheadExpr(imp.expr, AnySelectionProto) @@ -569,6 +550,28 @@ class Namer { typer: Typer => } } + class TypeDefCompleter(original: TypeDef)(ictx: Context) extends Completer(original)(ictx) with TypeParamsCompleter { + private var myTypeParams: List[TypeSymbol] = null + private var nestedCtx: Context = null + assert(!original.isClassDef) + + def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol] = { + if (myTypeParams == null) { + //println(i"completing type params of $sym in ${sym.owner}") + nestedCtx = localContext(sym).setNewScope + myTypeParams = { + implicit val ctx: Context = nestedCtx + completeParams(original.tparams) + original.tparams.map(symbolOfTree(_).asType) + } + } + myTypeParams + } + + override protected def typeSig(sym: Symbol): Type = + typeDefSig(original, sym, completerTypeParams(sym)(ictx))(nestedCtx) + } + class ClassCompleter(cls: ClassSymbol, original: TypeDef)(ictx: Context) extends Completer(original)(ictx) { withDecls(newScope) |