@@ -1197,17 +1197,17 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1197
1197
)
1198
1198
end typedIf
1199
1199
1200
- /** Decompose function prototype into a list of parameter prototypes, an optional list
1201
- * describing whether the parameter prototypes come from WildcardTypes, and a result prototype
1202
- * tree, using WildcardTypes where a type is not known .
1200
+ /** Decompose function prototype into a list of parameter prototypes and a result
1201
+ * prototype tree, using WildcardTypes where a type is not known.
1202
+ * Note: parameter prototypes may be TypeBounds .
1203
1203
* For the result type we do this even if the expected type is not fully
1204
1204
* defined, which is a bit of a hack. But it's needed to make the following work
1205
1205
* (see typers.scala and printers/PlainPrinter.scala for examples).
1206
1206
*
1207
1207
* def double(x: Char): String = s"$x$x"
1208
1208
* "abc" flatMap double
1209
1209
*/
1210
- private def decomposeProtoFunction (pt : Type , defaultArity : Int , pos : SrcPos )(using Context ): (List [Type ], Option [ List [ Boolean ]], untpd.Tree ) = {
1210
+ private def decomposeProtoFunction (pt : Type , defaultArity : Int , pos : SrcPos )(using Context ): (List [Type ], untpd.Tree ) = {
1211
1211
def typeTree (tp : Type ) = tp match {
1212
1212
case _ : WildcardType => new untpd.InferredTypeTree ()
1213
1213
case _ => untpd.InferredTypeTree (tp)
@@ -1235,26 +1235,19 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1235
1235
// if expected parameter type(s) are wildcards, approximate from below.
1236
1236
// if expected result type is a wildcard, approximate from above.
1237
1237
// this can type the greatest set of admissible closures.
1238
- // However, we still keep the information on whether expected parameter types were
1239
- // wildcards, in case of types inferred from target being more specific
1240
1238
1241
- val fromWildcards = pt1.argInfos.init.map{
1242
- case bounds @ TypeBounds (nt, at) if nt == defn.NothingType && at == defn.AnyType => true
1243
- case bounds => false
1244
- }
1245
-
1246
- (pt1.argTypesLo.init, Some (fromWildcards), typeTree(interpolateWildcards(pt1.argTypesHi.last)))
1239
+ (pt1.argInfos.init, typeTree(interpolateWildcards(pt1.argInfos.last.hiBound)))
1247
1240
case RefinedType (parent, nme.apply, mt @ MethodTpe (_, formals, restpe))
1248
1241
if defn.isNonRefinedFunction(parent) && formals.length == defaultArity =>
1249
- (formals, None , untpd.DependentTypeTree (syms => restpe.substParams(mt, syms.map(_.termRef))))
1242
+ (formals, untpd.DependentTypeTree (syms => restpe.substParams(mt, syms.map(_.termRef))))
1250
1243
case SAMType (mt @ MethodTpe (_, formals, restpe)) =>
1251
- (formals, None ,
1244
+ (formals,
1252
1245
if (mt.isResultDependent)
1253
1246
untpd.DependentTypeTree (syms => restpe.substParams(mt, syms.map(_.termRef)))
1254
1247
else
1255
1248
typeTree(restpe))
1256
1249
case _ =>
1257
- (List .tabulate(defaultArity)(alwaysWildcardType), None , untpd.TypeTree ())
1250
+ (List .tabulate(defaultArity)(alwaysWildcardType), untpd.TypeTree ())
1258
1251
}
1259
1252
}
1260
1253
}
@@ -1276,7 +1269,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1276
1269
* If both attempts fail, return `NoType`.
1277
1270
*/
1278
1271
def inferredFromTarget (
1279
- param : untpd.ValDef , formal : Type , calleeType : Type , paramIndex : Name => Int , isWildcardParam : Boolean )(using Context ): Type =
1272
+ param : untpd.ValDef , formal : Type , calleeType : Type , paramIndex : Name => Int )(using Context ): Type =
1280
1273
val target = calleeType.widen match
1281
1274
case mtpe : MethodType =>
1282
1275
val pos = paramIndex(param.name)
@@ -1289,7 +1282,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1289
1282
else NoType
1290
1283
case _ => NoType
1291
1284
if target.exists then formal <:< target
1292
- if ! isWildcardParam && isFullyDefined(formal, ForceDegree .flipBottom) then formal
1285
+ if ! formal.isExactlyNothing && isFullyDefined(formal, ForceDegree .flipBottom) then formal
1293
1286
else if target.exists && isFullyDefined(target, ForceDegree .flipBottom) then target
1294
1287
else NoType
1295
1288
@@ -1466,7 +1459,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1466
1459
case _ =>
1467
1460
}
1468
1461
1469
- val (protoFormals, areWildcardParams, resultTpt) = decomposeProtoFunction(pt, params.length, tree.srcPos)
1462
+ val (protoFormals, resultTpt) = decomposeProtoFunction(pt, params.length, tree.srcPos)
1470
1463
1471
1464
def protoFormal (i : Int ): Type =
1472
1465
if (protoFormals.length == params.length) protoFormals(i)
@@ -1482,11 +1475,13 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1482
1475
}
1483
1476
1484
1477
var desugared : untpd.Tree = EmptyTree
1485
- if protoFormals.length == 1 && params.length != 1 && ptIsCorrectProduct(protoFormals.head) then
1486
- val isGenericTuple =
1487
- protoFormals.head.derivesFrom(defn.TupleClass )
1488
- && ! defn.isTupleClass(protoFormals.head.typeSymbol)
1489
- desugared = desugar.makeTupledFunction(params, fnBody, isGenericTuple)
1478
+ if protoFormals.length == 1 && params.length != 1 then
1479
+ val firstFormal = protoFormals.head.loBound
1480
+ if ptIsCorrectProduct(firstFormal) then
1481
+ val isGenericTuple =
1482
+ firstFormal.derivesFrom(defn.TupleClass )
1483
+ && ! defn.isTupleClass(firstFormal.typeSymbol)
1484
+ desugared = desugar.makeTupledFunction(params, fnBody, isGenericTuple)
1490
1485
else if protoFormals.length > 1 && params.length == 1 then
1491
1486
def isParamRef (scrut : untpd.Tree ): Boolean = scrut match
1492
1487
case untpd.Annotated (scrut1, _) => isParamRef(scrut1)
@@ -1508,22 +1503,22 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1508
1503
for ((param, i) <- params.zipWithIndex) yield
1509
1504
if (! param.tpt.isEmpty) param
1510
1505
else
1511
- val formal = protoFormal(i)
1512
- val isWildcardParam = areWildcardParams.map(list => if i < list.length then list(i) else false ).getOrElse(false )
1506
+ val formalBounds = protoFormal(i)
1507
+ val formal = formalBounds.loBound
1508
+ val isBottomFromWildcard = (formalBounds ne formal) && formal.isExactlyNothing
1513
1509
val knownFormal = isFullyDefined(formal, ForceDegree .failBottom)
1514
- // Since decomposeProtoFunction eagerly approximates function arguments
1515
- // from below, then in the case that the argument was also identified as
1516
- // a wildcard type we try to prioritize inferring from target, if possible.
1517
- // See issue 16405 (tests/run/16405.scala)
1518
- val (usingFormal, paramType) =
1519
- if ! isWildcardParam && knownFormal then (true , formal)
1520
- else
1521
- val fromTarget = inferredFromTarget(param, formal, calleeType, paramIndex, isWildcardParam)
1522
- if fromTarget.exists then (false , fromTarget)
1523
- else if knownFormal then (true , formal)
1524
- else (false , errorType(AnonymousFunctionMissingParamType (param, tree, formal), param.srcPos))
1510
+ // If the expected formal is a TypeBounds wildcard argument with Nothing as lower bound,
1511
+ // try to prioritize inferring from target. See issue 16405 (tests/run/16405.scala)
1512
+ val paramType =
1513
+ if knownFormal && ! isBottomFromWildcard then
1514
+ formal
1515
+ else
1516
+ inferredFromTarget(param, formal, calleeType, paramIndex).orElse(
1517
+ if knownFormal then formal
1518
+ else errorType(AnonymousFunctionMissingParamType (param, tree, formal), param.srcPos)
1519
+ )
1525
1520
val paramTpt = untpd.TypedSplice (
1526
- (if usingFormal then InferredTypeTree () else untpd.TypeTree ())
1521
+ (if knownFormal then InferredTypeTree () else untpd.TypeTree ())
1527
1522
.withType(paramType.translateFromRepeated(toArray = false ))
1528
1523
.withSpan(param.span.endPos)
1529
1524
)
@@ -1594,7 +1589,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1594
1589
typedMatchFinish(tree, tpd.EmptyTree , defn.ImplicitScrutineeTypeRef , cases1, pt)
1595
1590
}
1596
1591
else {
1597
- val (protoFormals, _, _ ) = decomposeProtoFunction(pt, 1 , tree.srcPos)
1592
+ val (protoFormals, _) = decomposeProtoFunction(pt, 1 , tree.srcPos)
1598
1593
val checkMode =
1599
1594
if (pt.isRef(defn.PartialFunctionClass )) desugar.MatchCheck .None
1600
1595
else desugar.MatchCheck .Exhaustive
0 commit comments