Skip to content

Commit 1978b8b

Browse files
committed
Simplifications (2)
1 parent 4523a6f commit 1978b8b

File tree

1 file changed

+33
-38
lines changed

1 file changed

+33
-38
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)