aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala')
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala51
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 =>