1
1
package dotty .tools .dotc
2
2
package transform .localopt
3
3
4
- import scala .language .unsafeNulls
5
-
6
- import dotty .tools .dotc .ast .tpd
4
+ import dotty .tools .dotc .ast .tpd .*
7
5
import dotty .tools .dotc .core .Decorators .*
8
- import dotty .tools .dotc .core .Constants .Constant
9
6
import dotty .tools .dotc .core .Contexts .*
10
7
import dotty .tools .dotc .core .StdNames .*
11
8
import dotty .tools .dotc .core .Symbols .*
12
9
import dotty .tools .dotc .core .Types .*
13
10
import dotty .tools .dotc .transform .MegaPhase .MiniPhase
14
- import dotty .tools .dotc .typer .ConstFold
15
11
import dotty .tools .dotc .ast .desugar
16
- import scala .util .chaining .*
17
- import tpd .*
18
12
19
13
class DropForMap extends MiniPhase :
20
14
import DropForMap .*
21
- import Binder .*
22
15
23
16
override def phaseName : String = DropForMap .name
24
17
25
18
override def description : String = DropForMap .description
26
19
27
- override def transformApply (tree : tpd. Apply )(using Context ): tpd. Tree =
20
+ override def transformApply (tree : Apply )(using Context ): Tree =
28
21
if ! tree.hasAttachment(desugar.TrailingForMap ) then tree
29
22
else tree match
30
23
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
32
25
f // drop the map call
33
26
case _ =>
34
- tree.tap(_.removeAttachment(desugar.TrailingForMap ))
27
+ tree.removeAttachment(desugar.TrailingForMap )
28
+ tree
35
29
36
30
private object Lambda :
37
31
def unapply (tree : Tree )(using Context ): Option [(List [ValDef ], Tree )] =
38
32
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)) =>
40
35
Some ((defdef.termParamss.flatten, defdef.rhs))
41
36
case _ => None
42
37
@@ -47,57 +42,6 @@ class DropForMap extends MiniPhase:
47
42
case TypeApply (fn, _) => unapply(fn)
48
43
case _ => None
49
44
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
-
97
45
object DropForMap :
98
46
val name : String = " dropForMap"
99
47
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