@@ -26,25 +26,46 @@ object TypeApplications {
2626
2727 /** Extractor for
2828 *
29- * [v1 X1: B1, ..., vn Xn: Bn] -> C[X1, ..., Xn]
29+ * [X1: B1, ..., Xn: Bn] -> C[X1, ..., Xn]
3030 *
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.
3332 *
3433 * @param tycon C
3534 */
36- object EtaExpansion {
37- def apply (tycon : Type )(using Context ): Type = {
35+ object EtaExpansion :
36+
37+ def apply (tycon : Type )(using Context ): Type =
3838 assert(tycon.typeParams.nonEmpty, tycon)
3939 tycon.EtaExpand (tycon.typeParamSymbols)
40- }
4140
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 to workaround #9965 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
4361 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)
4566 case _ => None
46- }
47- }
67+
68+ end EtaExpansion
4869
4970 /** Adapt all arguments to possible higher-kinded type parameters using etaExpandIfHK
5071 */
0 commit comments