@@ -100,30 +100,38 @@ object Checking {
100
100
checkValidIfHKApply(ctx.addMode(Mode .AllowLambdaWildcardApply ))
101
101
}
102
102
103
- /** Check that the rank of the kind of `arg` does not exceed the rank of the
104
- * kind of `paramBounds`. E.g. if `paramBounds` has *-kind , `arg` must have
105
- * *-kind as well, and analogously for higher kinds.
106
- * More detailed kind checking is done as part of checkBounds in PostTyper.
107
- * The purpose of checkKindRank is to do a rough test earlier in Typer,
103
+ /** Check that kind of `arg` has the same outline as the kind of paramBounds.
104
+ * E.g. if `paramBounds` has kind * -> * , `arg` must have that kind as well,
105
+ * and analogously for all other kinds. This kind checking does not take into account
106
+ * variances or bounds. The more detailed kind checking is done as part of checkBounds in PostTyper.
107
+ * The purpose of preCheckKind is to do a rough test earlier in Typer,
108
108
* in order to prevent scenarios that lead to self application of
109
- * types. Self application needs to be avoided since it can lead to stackoverflows .
110
- * A test case is neg/i2771.scala.
109
+ * types. Self application needs to be avoided since it can lead to stack overflows .
110
+ * Test cases are neg/i2771.scala and neg/i2771b .scala.
111
111
*/
112
- def checkKindRank (arg : Tree , paramBounds : TypeBounds )(implicit ctx : Context ): Tree = {
112
+ def preCheckKind (arg : Tree , paramBounds : TypeBounds )(implicit ctx : Context ): Tree = {
113
113
def result (tp : Type ): Type = tp match {
114
114
case tp : HKTypeLambda => tp.resultType
115
115
case tp : TypeProxy => result(tp.superType)
116
116
case _ => defn.AnyType
117
117
}
118
- def kindOK (argType : Type , boundType : Type ): Boolean =
119
- ! argType.isHK ||
120
- boundType.isHK && kindOK(result(argType), result(boundType))
118
+ def kindOK (argType : Type , boundType : Type ): Boolean = {
119
+ // println(i"check kind rank2$arg $argType $boundType") // DEBUG
120
+ val argResult = argType.hkResult
121
+ val boundResult = argType.hkResult
122
+ if (argResult.exists)
123
+ boundResult.exists &&
124
+ kindOK(boundResult, argResult) &&
125
+ argType.typeParams.corresponds(boundType.typeParams)((ap, bp) =>
126
+ kindOK(ap.paramInfo, bp.paramInfo))
127
+ else ! boundResult.exists
128
+ }
121
129
if (kindOK(arg.tpe, paramBounds.hi)) arg
122
- else errorTree(arg, em " ${arg.tpe} takes type parameters " )
130
+ else errorTree(arg, em " ${arg.tpe} has wrong kind " )
123
131
}
124
132
125
- def checkKindRanks (args : List [Tree ], paramBoundss : List [TypeBounds ])(implicit ctx : Context ): List [Tree ] = {
126
- val args1 = args.zipWithConserve(paramBoundss)(checkKindRank )
133
+ def preCheckKinds (args : List [Tree ], paramBoundss : List [TypeBounds ])(implicit ctx : Context ): List [Tree ] = {
134
+ val args1 = args.zipWithConserve(paramBoundss)(preCheckKind )
127
135
args1 ++ args.drop(paramBoundss.length)
128
136
// add any arguments that do not correspond to a parameter back,
129
137
// so the wrong number of parameters is reported afterwards.
0 commit comments