@@ -47,6 +47,14 @@ object desugar {
4747 */
4848 val UntupledParam : Property .Key [Unit ] = Property .StickyKey ()
4949
50+ /** An attachment key to indicate that a ValDef originated from a pattern.
51+ */
52+ val PatternVar : Property .Key [Unit ] = Property .StickyKey ()
53+
54+ /** An attachment key for Trees originating in for-comprehension, such as tupling of assignments.
55+ */
56+ val ForArtifact : Property .Key [Unit ] = Property .StickyKey ()
57+
5058 /** An attachment key to indicate that a ValDef is an evidence parameter
5159 * for a context bound.
5260 */
@@ -56,6 +64,11 @@ object desugar {
5664 */
5765 val PolyFunctionApply : Property .Key [Unit ] = Property .StickyKey ()
5866
67+ /** An attachment key to indicate that an Apply is created as a last `map`
68+ * scall in a for-comprehension.
69+ */
70+ val TrailingForMap : Property .Key [Unit ] = Property .StickyKey ()
71+
5972 /** What static check should be applied to a Match? */
6073 enum MatchCheck {
6174 case None , Exhaustive , IrrefutablePatDef , IrrefutableGenFrom
@@ -410,6 +423,7 @@ object desugar {
410423 .withMods(Modifiers (
411424 meth.mods.flags & (AccessFlags | Synthetic ) | (vparam.mods.flags & Inline ),
412425 meth.mods.privateWithin))
426+ .withSpan(vparam.rhs.span)
413427 val rest = defaultGetters(vparams :: paramss1, n + 1 )
414428 if vparam.rhs.isEmpty then rest else defaultGetter :: rest
415429 case _ :: paramss1 => // skip empty parameter lists and type parameters
@@ -859,7 +873,7 @@ object desugar {
859873 val nu = vparamss.foldLeft(makeNew(classTypeRef)) { (nu, vparams) =>
860874 val app = Apply (nu, vparams.map(refOfDef))
861875 vparams match {
862- case vparam :: _ if vparam.mods.is( Given ) || vparam.name.is(ContextBoundParamName ) =>
876+ case vparam :: _ if vparam.mods.isOneOf( GivenOrImplicit ) || vparam.name.is(ContextBoundParamName ) =>
863877 app.setApplyKind(ApplyKind .Using )
864878 case _ => app
865879 }
@@ -1507,7 +1521,7 @@ object desugar {
15071521 val matchExpr =
15081522 if (tupleOptimizable) rhs
15091523 else
1510- val caseDef = CaseDef (pat, EmptyTree , makeTuple(ids))
1524+ val caseDef = CaseDef (pat, EmptyTree , makeTuple(ids).withAttachment( ForArtifact , ()) )
15111525 Match (makeSelector(rhs, MatchCheck .IrrefutablePatDef ), caseDef :: Nil )
15121526 vars match {
15131527 case Nil if ! mods.is(Lazy ) =>
@@ -1537,6 +1551,7 @@ object desugar {
15371551 ValDef (named.name.asTermName, tpt, selector(n))
15381552 .withMods(mods)
15391553 .withSpan(named.span)
1554+ .withAttachment(PatternVar , ())
15401555 )
15411556 flatTree(firstDef :: restDefs)
15421557 }
@@ -1922,6 +1937,7 @@ object desugar {
19221937 val vdef = ValDef (named.name.asTermName, tpt, rhs)
19231938 .withMods(mods)
19241939 .withSpan(original.span.withPoint(named.span.start))
1940+ .withAttachment(PatternVar , ())
19251941 val mayNeedSetter = valDef(vdef)
19261942 mayNeedSetter
19271943 }
@@ -1956,14 +1972,8 @@ object desugar {
19561972 *
19571973 * 3.
19581974 *
1959- * for (P <- G) yield P ==> G
1960- *
1961- * If betterFors is enabled, P is a variable or a tuple of variables and G is not a withFilter.
1962- *
19631975 * for (P <- G) yield E ==> G.map (P => E)
19641976 *
1965- * Otherwise
1966- *
19671977 * 4.
19681978 *
19691979 * for (P_1 <- G_1; P_2 <- G_2; ...) ...
@@ -2136,14 +2146,20 @@ object desugar {
21362146 case (Tuple (ts1), Tuple (ts2)) => ts1.corresponds(ts2)(deepEquals)
21372147 case _ => false
21382148
2149+ def markTrailingMap (aply : Apply , gen : GenFrom , selectName : TermName ): Unit =
2150+ if betterForsEnabled
2151+ && selectName == mapName
2152+ && gen.checkMode != GenCheckMode .Filtered // results of withFilter have the wrong type
2153+ && (deepEquals(gen.pat, body) || deepEquals(body, Tuple (Nil )))
2154+ then
2155+ aply.putAttachment(TrailingForMap , ())
2156+
21392157 enums match {
21402158 case Nil if betterForsEnabled => body
21412159 case (gen : GenFrom ) :: Nil =>
2142- if betterForsEnabled
2143- && gen.checkMode != GenCheckMode .Filtered // results of withFilter have the wrong type
2144- && deepEquals(gen.pat, body)
2145- then gen.expr // avoid a redundant map with identity
2146- else Apply (rhsSelect(gen, mapName), makeLambda(gen, body))
2160+ val aply = Apply (rhsSelect(gen, mapName), makeLambda(gen, body))
2161+ markTrailingMap(aply, gen, mapName)
2162+ aply
21472163 case (gen : GenFrom ) :: (rest @ (GenFrom (_, _, _) :: _)) =>
21482164 val cont = makeFor(mapName, flatMapName, rest, body)
21492165 Apply (rhsSelect(gen, flatMapName), makeLambda(gen, cont))
@@ -2154,7 +2170,9 @@ object desugar {
21542170 val selectName =
21552171 if rest.exists(_.isInstanceOf [GenFrom ]) then flatMapName
21562172 else mapName
2157- Apply (rhsSelect(gen, selectName), makeLambda(gen, cont))
2173+ val aply = Apply (rhsSelect(gen, selectName), makeLambda(gen, cont))
2174+ markTrailingMap(aply, gen, selectName)
2175+ aply
21582176 case (gen : GenFrom ) :: (rest @ GenAlias (_, _) :: _) =>
21592177 val (valeqs, rest1) = rest.span(_.isInstanceOf [GenAlias ])
21602178 val pats = valeqs map { case GenAlias (pat, _) => pat }
@@ -2167,7 +2185,7 @@ object desugar {
21672185 case _ => Modifiers ()
21682186 makePatDef(valeq, mods, defpat, rhs)
21692187 }
2170- val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom (defpat0, gen.expr, gen.checkMode) :: Nil , Block (pdefs, makeTuple(id0 :: ids)))
2188+ val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom (defpat0, gen.expr, gen.checkMode) :: Nil , Block (pdefs, makeTuple(id0 :: ids).withAttachment( ForArtifact , ()) ))
21712189 val allpats = gen.pat :: pats
21722190 val vfrom1 = GenFrom (makeTuple(allpats), rhs1, GenCheckMode .Ignore )
21732191 makeFor(mapName, flatMapName, vfrom1 :: rest1, body)
0 commit comments