Skip to content

Commit 1807f31

Browse files
committed
Simplify betterFors fix a lot
1 parent 961a3cd commit 1807f31

File tree

2 files changed

+9
-65
lines changed

2 files changed

+9
-65
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,7 +2151,7 @@ object desugar {
21512151
val aply = Apply(rhsSelect(gen, mapName), makeLambda(gen, body))
21522152
if betterForsEnabled
21532153
&& gen.checkMode != GenCheckMode.Filtered // results of withFilter have the wrong type
2154-
&& deepEquals(gen.pat, body)
2154+
&& (deepEquals(gen.pat, body) || deepEquals(body, Tuple(Nil)))
21552155
then
21562156
aply.putAttachment(TrailingForMap, ())
21572157
aply
@@ -2166,7 +2166,7 @@ object desugar {
21662166
if rest.exists(_.isInstanceOf[GenFrom]) then flatMapName
21672167
else mapName
21682168
val aply = Apply(rhsSelect(gen, selectName), makeLambda(gen, cont))
2169-
if selectName == mapName then
2169+
if selectName == mapName && (deepEquals(gen.pat, body) || deepEquals(body, Tuple(Nil))) then
21702170
aply.pushAttachment(TrailingForMap, ())
21712171
aply
21722172
case (gen: GenFrom) :: (rest @ GenAlias(_, _) :: _) =>
Lines changed: 7 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,37 @@
11
package dotty.tools.dotc
22
package transform.localopt
33

4-
import scala.language.unsafeNulls
5-
6-
import dotty.tools.dotc.ast.tpd
4+
import dotty.tools.dotc.ast.tpd.*
75
import dotty.tools.dotc.core.Decorators.*
8-
import dotty.tools.dotc.core.Constants.Constant
96
import dotty.tools.dotc.core.Contexts.*
107
import dotty.tools.dotc.core.StdNames.*
118
import dotty.tools.dotc.core.Symbols.*
129
import dotty.tools.dotc.core.Types.*
1310
import dotty.tools.dotc.transform.MegaPhase.MiniPhase
14-
import dotty.tools.dotc.typer.ConstFold
1511
import dotty.tools.dotc.ast.desugar
16-
import scala.util.chaining.*
17-
import tpd.*
1812

1913
class DropForMap extends MiniPhase:
2014
import DropForMap.*
21-
import Binder.*
2215

2316
override def phaseName: String = DropForMap.name
2417

2518
override def description: String = DropForMap.description
2619

27-
override def transformApply(tree: tpd.Apply)(using Context): tpd.Tree =
20+
override def transformApply(tree: Apply)(using Context): Tree =
2821
if !tree.hasAttachment(desugar.TrailingForMap) then tree
2922
else tree match
3023
case aply @ Apply(MapCall(f), List(Lambda(List(param), body)))
31-
if canDropMap(Single(param), body) && f.tpe =:= aply.tpe => // make sure that the type of the expression won't change
24+
if f.tpe =:= aply.tpe => // make sure that the type of the expression won't change
3225
f // drop the map call
3326
case _ =>
34-
tree.tap(_.removeAttachment(desugar.TrailingForMap))
27+
tree.removeAttachment(desugar.TrailingForMap)
28+
tree
3529

3630
private object Lambda:
3731
def unapply(tree: Tree)(using Context): Option[(List[ValDef], Tree)] =
3832
tree match
39-
case Block(List(defdef: DefDef), Closure(Nil, ref, _)) if ref.symbol == defdef.symbol && !defdef.paramss.exists(_.forall(_.isType)) =>
33+
case Block(List(defdef: DefDef), Closure(Nil, ref, _))
34+
if ref.symbol == defdef.symbol && !defdef.paramss.exists(_.forall(_.isType)) =>
4035
Some((defdef.termParamss.flatten, defdef.rhs))
4136
case _ => None
4237

@@ -47,57 +42,6 @@ class DropForMap extends MiniPhase:
4742
case TypeApply(fn, _) => unapply(fn)
4843
case _ => None
4944

50-
/** We can drop the map call if:
51-
* - it is a Unit literal
52-
* - is an identity function (i.e. the last pattern is the same as the result)
53-
*/
54-
private def canDropMap(params: Binder, tree: Tree)(using Context): Boolean = tree match
55-
case Literal(Constant(())) => params match
56-
case Single(bind) => bind.symbol.info.isRef(defn.UnitClass)
57-
case _ => false
58-
case ident: Ident => params match
59-
case Single(bind) => bind.symbol == ident.symbol
60-
case _ => false
61-
case tree: Apply if tree.tpe.typeSymbol.derivesFrom(defn.TupleClass) => params match
62-
case Tuple(binds) => tree.args.zip(binds).forall((arg, param) => canDropMap(param, arg))
63-
case _ => false
64-
case Match(scrutinee, List(CaseDef(pat, EmptyTree, body))) =>
65-
val newParams = newParamsFromMatch(params, scrutinee, pat)
66-
canDropMap(newParams, body)
67-
case Block(Nil, expr) => canDropMap(params, expr)
68-
case _ =>
69-
false
70-
71-
/** Extract potentially new parameters from a match expression
72-
*/
73-
private def newParamsFromMatch(params: Binder, scrutinee: Tree, pat: Tree)(using Context): Binder =
74-
def extractTraverse(pats: List[Tree]): Option[List[Binder]] = pats match
75-
case Nil => Some(List.empty)
76-
case pat :: pats =>
77-
extractBinders(pat).map(_ +: extractTraverse(pats).get)
78-
def extractBinders(pat: Tree): Option[Binder] = pat match
79-
case bind: Bind => Some(Single(bind))
80-
case tree @ UnApply(fun, implicits, pats)
81-
if implicits.isEmpty && tree.tpe.finalResultType.dealias.typeSymbol.derivesFrom(defn.TupleClass) =>
82-
extractTraverse(pats).map(Tuple.apply)
83-
case _ => None
84-
85-
params match
86-
case Single(bind) if scrutinee.symbol == bind.symbol =>
87-
pat match
88-
case bind: Bind => Single(bind)
89-
case tree @ UnApply(fun, implicits, pats) if implicits.isEmpty =>
90-
val unapplied = tree.tpe.finalResultType.dealias.typeSymbol
91-
if unapplied.derivesFrom(defn.TupleClass) then
92-
extractTraverse(pats).map(Tuple.apply).getOrElse(params)
93-
else params
94-
case _ => params
95-
case _ => params
96-
9745
object DropForMap:
9846
val name: String = "dropForMap"
9947
val description: String = "Drop unused trailing map calls in for comprehensions"
100-
101-
private enum Binder:
102-
case Single(bind: NamedDefTree)
103-
case Tuple(binds: List[Binder])

0 commit comments

Comments
 (0)