@@ -12,42 +12,62 @@ import dotty.tools.dotc.transform.MegaPhase.MiniPhase
12
12
import dotty .tools .dotc .ast .desugar
13
13
14
14
/** Drop unused trailing map calls in for comprehensions.
15
- * We can drop the map call if:
16
- * - it won't change the type of the expression, and
17
- * - the function is an identity function or a const function to unit.
18
- *
19
- * The latter condition is checked in [[Desugar.scala#makeFor ]]
20
- */
15
+ *
16
+ * We can drop the map call if:
17
+ * - it won't change the type of the expression, and
18
+ * - the function is an identity function or a const function to unit.
19
+ *
20
+ * The latter condition is checked in [[Desugar.scala#makeFor ]]
21
+ */
21
22
class DropForMap extends MiniPhase :
22
23
import DropForMap .*
23
24
24
25
override def phaseName : String = DropForMap .name
25
26
26
27
override def description : String = DropForMap .description
27
28
28
- override def transformApply (tree : Apply )(using Context ): Tree =
29
- tree.removeAttachment(desugar.TrailingForMap ) match
30
- case Some (_) =>
29
+ /** r.map(x => x)(using y) --> r
30
+ * ^ TrailingForMap
31
+ */
32
+ override def transformApply (tree : Apply )(using Context ): Tree = tree match
33
+ case Unmapped (f) =>
34
+ if f.tpe =:= tree.tpe then // make sure that the type of the expression won't change
35
+ f // drop the map call
36
+ else
37
+ f match
38
+ case Converted (r) if r.tpe =:= tree.tpe => r // drop the map call and the conversion
39
+ case _ => tree
40
+ case tree => tree
41
+
42
+ // Extracts a fun from a possibly nested Apply with lambda and arbitrary implicit args.
43
+ private object Unmapped :
44
+ private def loop (tree : Tree )(using Context ): Option [Tree ] =
31
45
tree match
32
- case aply @ Apply (MapCall (f), List (Lambda (List (param), body))) =>
33
- if f.tpe =:= aply.tpe then // make sure that the type of the expression won't change
34
- return f // drop the map call
35
- else
36
- f match
37
- case Converted (r) if r.tpe =:= aply.tpe =>
38
- return r // drop the map call and the conversion
46
+ case Apply (fun, Lambda (_ :: Nil , _) :: Nil ) =>
47
+ tree.removeAttachment(desugar.TrailingForMap ) match
48
+ case Some (_) =>
49
+ fun match
50
+ case MapCall (f) => return Some (f)
39
51
case _ =>
52
+ case _ =>
53
+ case Apply (fun, _) =>
54
+ fun.tpe match
55
+ case mt : MethodType if mt.isImplicitMethod => return loop(fun)
56
+ case _ =>
40
57
case _ =>
41
- case _ =>
42
- tree
58
+ None
59
+ end loop
60
+ def unapply (tree : Apply )(using Context ): Option [Tree ] =
61
+ tree.tpe match
62
+ case _ : MethodOrPoly => None
63
+ case _ => loop(tree)
43
64
44
65
private object Lambda :
45
- def unapply (tree : Tree )(using Context ): Option [(List [ValDef ], Tree )] =
46
- tree match
47
- case Block (List (defdef : DefDef ), Closure (Nil , ref, _))
48
- if ref.symbol == defdef.symbol && ! defdef.paramss.exists(_.forall(_.isType)) =>
49
- Some ((defdef.termParamss.flatten, defdef.rhs))
50
- case _ => None
66
+ def unapply (tree : Tree )(using Context ): Option [(List [ValDef ], Tree )] = tree match
67
+ case Block (List (defdef : DefDef ), Closure (Nil , ref, _))
68
+ if ref.symbol == defdef.symbol && ! defdef.paramss.exists(_.forall(_.isType)) =>
69
+ Some ((defdef.termParamss.flatten, defdef.rhs))
70
+ case _ => None
51
71
52
72
private object MapCall :
53
73
def unapply (tree : Tree )(using Context ): Option [Tree ] = tree match
0 commit comments