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/core/SymDenotations.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/core/SymDenotations.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 46d93b753..54884a24c 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1213,15 +1213,25 @@ object SymDenotations { private[this] var myNamedTypeParams: Set[TypeSymbol] = _ + /** The type parameters in this class, in the order they appear in the current + * scope `decls`. This is might be temporarily the incorrect order when + * reading Scala2 pickled info. The problem is fixed by `updateTypeParams` + * which is called once an unpickled symbol has been completed. + */ + private def typeParamsFromDecls(implicit ctx: Context) = + unforcedDecls.filter(sym => + (sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]] + /** The type parameters of this class */ override final def typeParams(implicit ctx: Context): List[TypeSymbol] = { - def computeTypeParams = { - if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls - else if (this ne initial) initial.asSymDenotation.typeParams - else unforcedDecls.filter(sym => - (sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]] - } - if (myTypeParams == null) myTypeParams = computeTypeParams + if (myTypeParams == null) + myTypeParams = + if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls + else if (this ne initial) initial.asSymDenotation.typeParams + else infoOrCompleter match { + case info: TypeParamsCompleter => info.completerTypeParams(symbol) + case _ => typeParamsFromDecls + } myTypeParams } @@ -1537,16 +1547,16 @@ object SymDenotations { if (myMemberCache != null) myMemberCache invalidate sym.name } - /** Make sure the type parameters of this class are `tparams`, reorder definitions - * in scope if necessary. + /** Make sure the type parameters of this class appear in the order given + * by `tparams` in the scope of the class. Reorder definitions in scope if necessary. * @pre All type parameters in `tparams` are entered in class scope `info.decls`. */ def updateTypeParams(tparams: List[Symbol])(implicit ctx: Context): Unit = - if (!typeParams.corresponds(tparams)(_.name == _.name)) { + if (!ctx.erasedTypes && !typeParamsFromDecls.corresponds(typeParams)(_.name == _.name)) { val decls = info.decls val decls1 = newScope for (tparam <- tparams) decls1.enter(decls.lookup(tparam.name)) - for (sym <- decls) if (!typeParams.contains(sym)) decls1.enter(sym) + for (sym <- decls) if (!tparams.contains(sym)) decls1.enter(sym) info = classInfo.derivedClassInfo(decls = decls1) myTypeParams = null } @@ -1868,9 +1878,9 @@ object SymDenotations { /** A subclass of LazyTypes where type parameters can be completed independently of * the info. */ - abstract class TypeParamsCompleter extends LazyType { + trait TypeParamsCompleter extends LazyType { /** The type parameters computed by the completer before completion has finished */ - def completerTypeParams(sym: Symbol): List[TypeSymbol] + def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol] } val NoSymbolFn = (ctx: Context) => NoSymbol |