@@ -1197,17 +1197,17 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
11971197 )
11981198 end typedIf
11991199
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 .
12031203 * For the result type we do this even if the expected type is not fully
12041204 * defined, which is a bit of a hack. But it's needed to make the following work
12051205 * (see typers.scala and printers/PlainPrinter.scala for examples).
12061206 *
12071207 * def double(x: Char): String = s"$x$x"
12081208 * "abc" flatMap double
12091209 */
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 ) = {
12111211 def typeTree (tp : Type ) = tp match {
12121212 case _ : WildcardType => new untpd.InferredTypeTree ()
12131213 case _ => untpd.InferredTypeTree (tp)
@@ -1235,26 +1235,19 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
12351235 // if expected parameter type(s) are wildcards, approximate from below.
12361236 // if expected result type is a wildcard, approximate from above.
12371237 // 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
12401238
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)))
12471240 case RefinedType (parent, nme.apply, mt @ MethodTpe (_, formals, restpe))
12481241 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))))
12501243 case SAMType (mt @ MethodTpe (_, formals, restpe)) =>
1251- (formals, None ,
1244+ (formals,
12521245 if (mt.isResultDependent)
12531246 untpd.DependentTypeTree (syms => restpe.substParams(mt, syms.map(_.termRef)))
12541247 else
12551248 typeTree(restpe))
12561249 case _ =>
1257- (List .tabulate(defaultArity)(alwaysWildcardType), None , untpd.TypeTree ())
1250+ (List .tabulate(defaultArity)(alwaysWildcardType), untpd.TypeTree ())
12581251 }
12591252 }
12601253 }
@@ -1276,7 +1269,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
12761269 * If both attempts fail, return `NoType`.
12771270 */
12781271 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 =
12801273 val target = calleeType.widen match
12811274 case mtpe : MethodType =>
12821275 val pos = paramIndex(param.name)
@@ -1289,7 +1282,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
12891282 else NoType
12901283 case _ => NoType
12911284 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
12931286 else if target.exists && isFullyDefined(target, ForceDegree .flipBottom) then target
12941287 else NoType
12951288
@@ -1466,7 +1459,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
14661459 case _ =>
14671460 }
14681461
1469- val (protoFormals, areWildcardParams, resultTpt) = decomposeProtoFunction(pt, params.length, tree.srcPos)
1462+ val (protoFormals, resultTpt) = decomposeProtoFunction(pt, params.length, tree.srcPos)
14701463
14711464 def protoFormal (i : Int ): Type =
14721465 if (protoFormals.length == params.length) protoFormals(i)
@@ -1482,11 +1475,13 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
14821475 }
14831476
14841477 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)
14901485 else if protoFormals.length > 1 && params.length == 1 then
14911486 def isParamRef (scrut : untpd.Tree ): Boolean = scrut match
14921487 case untpd.Annotated (scrut1, _) => isParamRef(scrut1)
@@ -1508,22 +1503,22 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
15081503 for ((param, i) <- params.zipWithIndex) yield
15091504 if (! param.tpt.isEmpty) param
15101505 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
15131509 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+ )
15251520 val paramTpt = untpd.TypedSplice (
1526- (if usingFormal then InferredTypeTree () else untpd.TypeTree ())
1521+ (if knownFormal then InferredTypeTree () else untpd.TypeTree ())
15271522 .withType(paramType.translateFromRepeated(toArray = false ))
15281523 .withSpan(param.span.endPos)
15291524 )
@@ -1594,7 +1589,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
15941589 typedMatchFinish(tree, tpd.EmptyTree , defn.ImplicitScrutineeTypeRef , cases1, pt)
15951590 }
15961591 else {
1597- val (protoFormals, _, _ ) = decomposeProtoFunction(pt, 1 , tree.srcPos)
1592+ val (protoFormals, _) = decomposeProtoFunction(pt, 1 , tree.srcPos)
15981593 val checkMode =
15991594 if (pt.isRef(defn.PartialFunctionClass )) desugar.MatchCheck .None
16001595 else desugar.MatchCheck .Exhaustive
0 commit comments