diff options
Diffstat (limited to 'src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 321846de6..d58122f2d 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -112,8 +112,6 @@ object Scala2Unpickler { if (tsym.exists) tsym.setFlag(TypeParam) else denot.enter(tparam, decls) } - denot.info = ClassInfo( - denot.owner.thisType, denot.classSymbol, parentRefs, decls, ost) // more refined infowith parents if (!(denot.flagsUNSAFE is JavaModule)) ensureConstructor(denot.symbol.asClass, decls) val scalacCompanion = denot.classSymbol.scalacLinkedClass @@ -151,6 +149,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 +766,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 => |