@@ -26,25 +26,46 @@ object TypeApplications {
26
26
27
27
/** Extractor for
28
28
*
29
- * [v1 X1: B1, ..., vn Xn: Bn] -> C[X1, ..., Xn]
29
+ * [X1: B1, ..., Xn: Bn] -> C[X1, ..., Xn]
30
30
*
31
- * where v1, ..., vn and B1, ..., Bn are the variances and bounds of the type parameters
32
- * of the class C.
31
+ * where B1, ..., Bn are bounds of the type parameters of the class C.
33
32
*
34
33
* @param tycon C
35
34
*/
36
- object EtaExpansion {
37
- def apply (tycon : Type )(using Context ): Type = {
35
+ object EtaExpansion :
36
+
37
+ def apply (tycon : Type )(using Context ): Type =
38
38
assert(tycon.typeParams.nonEmpty, tycon)
39
39
tycon.EtaExpand (tycon.typeParamSymbols)
40
- }
41
40
42
- def unapply (tp : Type )(using Context ): Option [Type ] = tp match {
41
+ /** Test that the parameter bounds in a hk type lambda `[X1,...,Xn] => C[X1, ..., Xn]`
42
+ * contain the bounds of the type parameters of `C`. This is necessary to be able to
43
+ * contract the hk lambda to `C`.
44
+ */
45
+ private def weakerBounds (tp : HKTypeLambda , tparams : List [ParamInfo ])(using Context ): Boolean =
46
+ val onlyEmptyBounds = tp.typeParams.forall(_.paramInfo == TypeBounds .empty)
47
+ onlyEmptyBounds
48
+ // Note: this pre-test helps efficiency. It is also necessary since in some cases
49
+ // tparams is empty. This can happen when we change the owners of inlined local
50
+ // classes in mapSymbols. See pos/reference/delegates.scala for an example.
51
+ // In this case, we can still return true if we know that the hk lambda bounds
52
+ // are empty anyway.
53
+ || {
54
+ val paramRefs = tparams.map(_.paramRef)
55
+ tp.typeParams.corresponds(tparams) { (param1, param2) =>
56
+ param2.paramInfo <:< param1.paramInfo.substParams(tp, paramRefs)
57
+ }
58
+ }
59
+
60
+ def unapply (tp : Type )(using Context ): Option [Type ] = tp match
43
61
case tp @ HKTypeLambda (tparams, AppliedType (fn : Type , args))
44
- if args.lazyZip(tparams).forall((arg, tparam) => arg == tparam.paramRef) => Some (fn)
62
+ if fn.typeSymbol.isClass
63
+ && tparams.hasSameLengthAs(args)
64
+ && args.lazyZip(tparams).forall((arg, tparam) => arg == tparam.paramRef)
65
+ && weakerBounds(tp, fn.typeParams) => Some (fn)
45
66
case _ => None
46
- }
47
- }
67
+
68
+ end EtaExpansion
48
69
49
70
/** Adapt all arguments to possible higher-kinded type parameters using etaExpandIfHK
50
71
*/
0 commit comments