@@ -1116,7 +1116,7 @@ class Typer extends Namer
1116
1116
* def double(x: Char): String = s"$x$x"
1117
1117
* "abc" flatMap double
1118
1118
*/
1119
- private def decomposeProtoFunction (pt : Type , defaultArity : Int , tree : untpd. Tree )(using Context ): (List [Type ], untpd.Tree ) = {
1119
+ private def decomposeProtoFunction (pt : Type , defaultArity : Int , pos : SrcPos )(using Context ): (List [Type ], untpd.Tree ) = {
1120
1120
def typeTree (tp : Type ) = tp match {
1121
1121
case _ : WildcardType => untpd.TypeTree ()
1122
1122
case _ => untpd.TypeTree (tp)
@@ -1135,11 +1135,10 @@ class Typer extends Namer
1135
1135
report.error(
1136
1136
i """ Implementation restriction: Expected result type $pt1
1137
1137
|is a curried dependent context function type. Such types are not yet supported. """ ,
1138
- tree.srcPos)
1139
-
1138
+ pos)
1140
1139
pt1 match {
1141
1140
case tp : TypeParamRef =>
1142
- decomposeProtoFunction(ctx.typerState.constraint.entry(tp).bounds.hi, defaultArity, tree )
1141
+ decomposeProtoFunction(ctx.typerState.constraint.entry(tp).bounds.hi, defaultArity, pos )
1143
1142
case _ => pt1.findFunctionTypeInUnion match {
1144
1143
case pt1 if defn.isNonRefinedFunction(pt1) =>
1145
1144
// if expected parameter type(s) are wildcards, approximate from below.
@@ -1161,6 +1160,37 @@ class Typer extends Namer
1161
1160
}
1162
1161
}
1163
1162
1163
+ /** The parameter type for a parameter in a lambda that does
1164
+ * not have an explicit type given, and where the type is not known from the context.
1165
+ * In this case the paranmeter type needs to be inferred the "target type" T known
1166
+ * from the callee `f` if the lambda is of a form like `x => f(x)`.
1167
+ * If `T` exists, we know that `S <: I <: T`.
1168
+ *
1169
+ * The inference makes two attempts:
1170
+ *
1171
+ * 1. Compute the target type `T` and make it known that `S <: T`.
1172
+ * If the expected type `S` can be fully defined under ForceDegree.flipBottom,
1173
+ * pick this one (this might use the fact that S <: T for an upper approximation).
1174
+ * 2. Otherwise, if the target type `T` can be fully defined under ForceDegree.flipBottom,
1175
+ * pick this one.
1176
+ *
1177
+ * If both attempts fail, issue a "missing parameter type" error.
1178
+ */
1179
+ def inferredFromTarget (
1180
+ param : untpd.ValDef , formal : Type , calleeType : Type , paramIndex : Name => Int )(using Context ): Type =
1181
+ val target = calleeType.widen match
1182
+ case mtpe : MethodType =>
1183
+ val pos = paramIndex(param.name)
1184
+ if pos < mtpe.paramInfos.length then
1185
+ val ptype = mtpe.paramInfos(pos)
1186
+ if ptype.isRepeatedParam then NoType else ptype
1187
+ else NoType
1188
+ case _ => NoType
1189
+ if target.exists then formal <:< target
1190
+ if isFullyDefined(formal, ForceDegree .flipBottom) then formal
1191
+ else if target.exists && isFullyDefined(target, ForceDegree .flipBottom) then target
1192
+ else NoType
1193
+
1164
1194
def typedFunction (tree : untpd.Function , pt : Type )(using Context ): Tree =
1165
1195
if (ctx.mode is Mode .Type ) typedFunctionType(tree, pt)
1166
1196
else typedFunctionValue(tree, pt)
@@ -1333,41 +1363,7 @@ class Typer extends Namer
1333
1363
case _ =>
1334
1364
}
1335
1365
1336
- val (protoFormals, resultTpt) = decomposeProtoFunction(pt, params.length, tree)
1337
-
1338
- /** The inferred parameter type for a parameter in a lambda that does
1339
- * not have an explicit type given.
1340
- * An inferred parameter type I has two possible sources:
1341
- * - the type S known from the context
1342
- * - the "target type" T known from the callee `f` if the lambda is of a form like `x => f(x)`
1343
- * If `T` exists, we know that `S <: I <: T`.
1344
- *
1345
- * The inference makes three attempts:
1346
- *
1347
- * 1. If the expected type `S` is already fully defined under ForceDegree.failBottom
1348
- * pick this one.
1349
- * 2. Compute the target type `T` and make it known that `S <: T`.
1350
- * If the expected type `S` can be fully defined under ForceDegree.flipBottom,
1351
- * pick this one (this might use the fact that S <: T for an upper approximation).
1352
- * 3. Otherwise, if the target type `T` can be fully defined under ForceDegree.flipBottom,
1353
- * pick this one.
1354
- *
1355
- * If all attempts fail, issue a "missing parameter type" error.
1356
- */
1357
- def inferredParamType (param : untpd.ValDef , formal : Type ): Type =
1358
- if isFullyDefined(formal, ForceDegree .failBottom) then return formal
1359
- val target = calleeType.widen match
1360
- case mtpe : MethodType =>
1361
- val pos = paramIndex(param.name)
1362
- if pos < mtpe.paramInfos.length then
1363
- val ptype = mtpe.paramInfos(pos)
1364
- if ptype.isRepeatedParam then NoType else ptype
1365
- else NoType
1366
- case _ => NoType
1367
- if target.exists then formal <:< target
1368
- if isFullyDefined(formal, ForceDegree .flipBottom) then formal
1369
- else if target.exists && isFullyDefined(target, ForceDegree .flipBottom) then target
1370
- else errorType(AnonymousFunctionMissingParamType (param, params, tree, formal), param.srcPos)
1366
+ val (protoFormals, resultTpt) = decomposeProtoFunction(pt, params.length, tree.srcPos)
1371
1367
1372
1368
def protoFormal (i : Int ): Type =
1373
1369
if (protoFormals.length == params.length) protoFormals(i)
@@ -1393,9 +1389,19 @@ class Typer extends Namer
1393
1389
val inferredParams : List [untpd.ValDef ] =
1394
1390
for ((param, i) <- params.zipWithIndex) yield
1395
1391
if (! param.tpt.isEmpty) param
1396
- else cpy.ValDef (param)(
1397
- tpt = untpd.TypeTree (
1398
- inferredParamType(param, protoFormal(i)).translateFromRepeated(toArray = false )))
1392
+ else
1393
+ val formal = protoFormal(i)
1394
+ val knownFormal = isFullyDefined(formal, ForceDegree .failBottom)
1395
+ val paramType =
1396
+ if knownFormal then formal
1397
+ else inferredFromTarget(param, formal, calleeType, paramIndex)
1398
+ .orElse(errorType(AnonymousFunctionMissingParamType (param, tree, formal), param.srcPos))
1399
+ val paramTpt = untpd.TypedSplice (
1400
+ (if knownFormal then InferredTypeTree () else untpd.TypeTree ())
1401
+ .withType(paramType.translateFromRepeated(toArray = false ))
1402
+ .withSpan(param.span.endPos)
1403
+ )
1404
+ cpy.ValDef (param)(tpt = paramTpt)
1399
1405
desugar.makeClosure(inferredParams, fnBody, resultTpt, isContextual, tree.span)
1400
1406
}
1401
1407
typed(desugared, pt)
@@ -1461,7 +1467,7 @@ class Typer extends Namer
1461
1467
typedMatchFinish(tree, tpd.EmptyTree , defn.ImplicitScrutineeTypeRef , cases1, pt)
1462
1468
}
1463
1469
else {
1464
- val (protoFormals, _) = decomposeProtoFunction(pt, 1 , tree)
1470
+ val (protoFormals, _) = decomposeProtoFunction(pt, 1 , tree.srcPos )
1465
1471
val checkMode =
1466
1472
if (pt.isRef(defn.PartialFunctionClass )) desugar.MatchCheck .None
1467
1473
else desugar.MatchCheck .Exhaustive
0 commit comments