diff options
author | Martin Odersky <odersky@gmail.com> | 2015-11-11 18:19:28 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-11-17 13:49:53 +0100 |
commit | d53da9502fe0cb98ed5f8dfe64fbc6e62c0e3368 (patch) | |
tree | 0ee14895c030b210be039e27649b790c674e660a /src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | |
parent | 6b061b5b94fb4e13a97274b28e0ab9ac78b69f27 (diff) | |
download | dotty-d53da9502fe0cb98ed5f8dfe64fbc6e62c0e3368.tar.gz dotty-d53da9502fe0cb98ed5f8dfe64fbc6e62c0e3368.tar.bz2 dotty-d53da9502fe0cb98ed5f8dfe64fbc6e62c0e3368.zip |
Eta expand according to expected type parameter variance
When eta expanding a type `C` to `[vX] => C[X]` the variance `v`
is now the variance of the expected type, not the variance of the
type constructor `C`, as long as the variance of the expected type
is compatible with the variance of `C`.
Diffstat (limited to 'src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 321846de6..8f4b47058 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -151,6 +151,51 @@ object Scala2Unpickler { denot.info = ClassInfo( // final info denot.owner.thisType, denot.classSymbol, parentRefs, declsInRightOrder, ost) } + + /** Adapt arguments to type parameters so that variance of type lambda arguments + * agrees with variance of corresponding higherkinded type parameters. Example: + * + * class Companion[+CC[X]] + * Companion[List] + * + * with adaptArgs, this will expand to + * + * Companion[[X] => List[X]] + * + * instead of + * + * Companion[[+X] => List[X]] + * + * even though `List` is covariant. This adaptation is necessary to ignore conflicting + * variances in overriding members that have types of hk-type parameters such as `Companion[GenTraversable]` + * or `Companion[ListBuffer]`. Without the adaptation we would end up with + * + * Companion[[+X] => GenTraversable[X]] + * Companion[[X] => List[X]] + * + * and the second is not a subtype of the first. So if we have overridding memebrs of the two + * types we get an error. + */ + def adaptArgs(tparams: List[Symbol], args: List[Type])(implicit ctx: Context): List[Type] = tparams match { + case tparam :: tparams1 => + val boundLambda = tparam.infoOrCompleter match { + case TypeBounds(_, hi) => hi.LambdaClass(forcing = false) + case _ => NoSymbol + } + def adaptArg(arg: Type): Type = arg match { + case arg: TypeRef if arg.symbol.isLambdaTrait => + assert(arg.symbol.typeParams.length == boundLambda.typeParams.length) + arg.prefix.select(boundLambda) + case arg: RefinedType => + arg.derivedRefinedType(adaptArg(arg.parent), arg.refinedName, arg.refinedInfo) + case _ => + arg + } + val arg = args.head + val adapted = if (boundLambda.exists) adaptArg(arg) else arg + adapted :: adaptArgs(tparams1, args.tail) + case nil => args + } } /** Unpickle symbol table information descending from a class and/or module root @@ -723,8 +768,8 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas else TypeRef(pre, sym.name.asTypeName) val args = until(end, readTypeRef) if (sym == defn.ByNameParamClass2x) ExprType(args.head) - else if (args.isEmpty && sym.typeParams.nonEmpty) tycon.EtaExpand - else tycon.appliedTo(args) + else if (args.isEmpty && sym.typeParams.nonEmpty) tycon.EtaExpand(sym.typeParams) + else tycon.appliedTo(adaptArgs(sym.typeParams, args)) case TYPEBOUNDStpe => TypeBounds(readTypeRef(), readTypeRef()) case REFINEDtpe => |