aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeApplications.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeApplications.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala59
1 files changed, 35 insertions, 24 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index b2f22da20..f7727779d 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -167,11 +167,11 @@ object TypeApplications {
}
}
- /** Adapt all arguments to possible higher-kinded type parameters using adaptIfHK
+ /** Adapt all arguments to possible higher-kinded type parameters using etaExpandIfHK
*/
- def adaptArgs(tparams: List[Symbol], args: List[Type])(implicit ctx: Context): List[Type] =
+ def etaExpandIfHK(tparams: List[Symbol], args: List[Type])(implicit ctx: Context): List[Type] =
if (tparams.isEmpty) args
- else args.zipWithConserve(tparams)((arg, tparam) => arg.adaptIfHK(tparam.infoOrCompleter))
+ else args.zipWithConserve(tparams)((arg, tparam) => arg.etaExpandIfHK(tparam.infoOrCompleter))
def argRefs(rt: RefinedType, n: Int)(implicit ctx: Context) =
List.range(0, n).map(i => RefinedThis(rt).select(tpnme.hkArg(i)))
@@ -340,11 +340,21 @@ class TypeApplications(val self: Type) extends AnyVal {
self.EtaExpand(self.typeParams)
}
- /** Adapt argument A to type parameter P in the case P is higher-kinded.
- * This means:
- * (1) Make sure that A is a type lambda, if necessary by eta-expanding it.
- * (2) Make sure the variances of the type lambda
- * agrees with variances of corresponding higherkinded type parameters. Example:
+ /** Eta expand if `self` is a (non-lambda) class reference and `bound` is a higher-kinded type */
+ def etaExpandIfHK(bound: Type)(implicit ctx: Context): Type = {
+ val boundLambda = bound.LambdaTrait
+ val hkParams = boundLambda.typeParams
+ if (hkParams.isEmpty) self
+ else self match {
+ case self: TypeRef if self.symbol.isClass && self.typeParams.length == hkParams.length =>
+ EtaExpansion(self)
+ case _ => self
+ }
+ }
+
+ /** If argument A and type parameter P are higher-kinded, adapt the variances
+ * of A to those of P, ensuring that the variances of the type lambda A
+ * agree with the variances of corresponding higherkinded type parameters of P. Example:
*
* class Companion[+CC[X]]
* Companion[List]
@@ -367,25 +377,26 @@ class TypeApplications(val self: Type) extends AnyVal {
* 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 adaptIfHK(bound: Type)(implicit ctx: Context): Type = {
+ def adaptHkVariances(bound: Type)(implicit ctx: Context): Type = {
val boundLambda = bound.LambdaTrait
val hkParams = boundLambda.typeParams
if (hkParams.isEmpty) self
- else self match {
- case self: TypeRef if self.symbol.isClass && self.typeParams.length == hkParams.length =>
- EtaExpansion(self).adaptIfHK(bound)
- case _ =>
- def adaptArg(arg: Type): Type = arg match {
- case arg: TypeRef
- if arg.symbol.isLambdaTrait &&
- !arg.symbol.typeParams.corresponds(boundLambda.typeParams)(_.variance == _.variance) =>
- arg.prefix.select(boundLambda)
- case arg: RefinedType =>
- arg.derivedRefinedType(adaptArg(arg.parent), arg.refinedName, arg.refinedInfo)
- case _ =>
- arg
- }
- adaptArg(self)
+ else {
+ def adaptArg(arg: Type): Type = arg match {
+ case arg: TypeRef if arg.symbol.isLambdaTrait &&
+ !arg.symbol.typeParams.corresponds(hkParams)(_.variance == _.variance) &&
+ arg.symbol.typeParams.corresponds(hkParams)(varianceConforms) =>
+ arg.prefix.select(boundLambda)
+ case arg: RefinedType =>
+ arg.derivedRefinedType(adaptArg(arg.parent), arg.refinedName, arg.refinedInfo)
+ case arg @ TypeAlias(alias) =>
+ arg.derivedTypeAlias(adaptArg(alias))
+ case arg @ TypeBounds(lo, hi) =>
+ arg.derivedTypeBounds(lo, adaptArg(hi))
+ case _ =>
+ arg
+ }
+ adaptArg(self)
}
}