@@ -13,13 +13,14 @@ import util.{Property, SourceFile, SourcePosition, SrcPos, Chars}
13
13
import config .{Feature , Config }
14
14
import config .Feature .{sourceVersion , migrateTo3 , enabled }
15
15
import config .SourceVersion .*
16
- import collection .mutable
17
16
import reporting .*
18
17
import printing .Formatting .hl
19
18
import config .Printers
20
19
import parsing .Parsers
20
+ import dotty .tools .dotc .util .chaining .*
21
21
22
22
import scala .annotation .{unchecked as _ , * }, internal .sharable
23
+ import scala .collection .mutable , mutable .ListBuffer
23
24
24
25
object desugar {
25
26
import untpd .*
@@ -272,12 +273,12 @@ object desugar {
272
273
*/
273
274
private def desugarContextBounds (
274
275
tdef : TypeDef ,
275
- evidenceBuf : mutable. ListBuffer [ValDef ],
276
+ evidenceBuf : ListBuffer [ValDef ],
276
277
evidenceFlags : FlagSet ,
277
278
freshName : untpd.Tree => TermName ,
278
279
allParamss : List [ParamClause ])(using Context ): TypeDef =
279
280
280
- val evidenceNames = mutable. ListBuffer [TermName ]()
281
+ val evidenceNames = ListBuffer .empty [TermName ]
281
282
282
283
def desugarRHS (rhs : Tree ): Tree = rhs match
283
284
case ContextBounds (tbounds, ctxbounds) =>
@@ -322,7 +323,7 @@ object desugar {
322
323
end desugarContextBounds
323
324
324
325
def elimContextBounds (meth : Tree , isPrimaryConstructor : Boolean = false )(using Context ): Tree =
325
- val evidenceParamBuf = mutable. ListBuffer [ValDef ]()
326
+ val evidenceParamBuf = ListBuffer .empty [ValDef ]
326
327
var seenContextBounds : Int = 0
327
328
def freshName (unused : Tree ) =
328
329
seenContextBounds += 1 // Start at 1 like FreshNameCreator.
@@ -647,7 +648,7 @@ object desugar {
647
648
* ultimately map to deferred givens.
648
649
*/
649
650
def typeDef (tdef : TypeDef )(using Context ): Tree =
650
- val evidenceBuf = new mutable. ListBuffer [ValDef ]
651
+ val evidenceBuf = ListBuffer .empty [ValDef ]
651
652
val result = desugarContextBounds(
652
653
tdef, evidenceBuf,
653
654
(tdef.mods.flags.toTermFlags & AccessFlags ) | Lazy | DeferredGivenFlags ,
@@ -1343,7 +1344,7 @@ object desugar {
1343
1344
)).withSpan(tree.span)
1344
1345
end makePolyFunctionType
1345
1346
1346
- /** Invent a name for an anonympus given of type or template `impl`. */
1347
+ /** Invent a name for an anonymous given of type or template `impl`. */
1347
1348
def inventGivenName (impl : Tree )(using Context ): SimpleName =
1348
1349
val str = impl match
1349
1350
case impl : Template =>
@@ -1422,7 +1423,7 @@ object desugar {
1422
1423
ids.map(expand(_, false ))
1423
1424
else {
1424
1425
val pats1 = if (tpt.isEmpty) pats else pats map (Typed (_, tpt))
1425
- pats1 map (makePatDef(pdef, mods, _, rhs))
1426
+ pats1. map(makePatDef(original = pdef, mods, _, rhs))
1426
1427
}
1427
1428
}
1428
1429
@@ -1453,10 +1454,10 @@ object desugar {
1453
1454
* val/var/lazy val p = e
1454
1455
*
1455
1456
* Otherwise, in case there is exactly one variable x_1 in pattern
1456
- * val/var/lazy val p = e ==> val/var/lazy val x_1 = (e: @unchecked) match (case p => (x_1))
1457
+ * val/var/lazy val p = e ==> val/var/lazy val x_1 = (e: @unchecked) match (case p => (x_1))
1457
1458
*
1458
1459
* in case there are zero or more than one variables in pattern
1459
- * val/var/lazy p = e ==> private[this] synthetic [lazy] val t$ = (e: @unchecked) match (case p => (x_1, ..., x_N))
1460
+ * val/var/lazy p = e ==> private[this] synthetic [lazy] val t$ = (e: @unchecked) match (case p => (x_1, ..., x_N))
1460
1461
* val/var/def x_1 = t$._1
1461
1462
* ...
1462
1463
* val/var/def x_N = t$._N
@@ -1470,6 +1471,7 @@ object desugar {
1470
1471
then cpy.Ident (id)(WildcardParamName .fresh())
1471
1472
else id
1472
1473
derivedValDef(original, id1, tpt, rhs, mods)
1474
+
1473
1475
case _ =>
1474
1476
1475
1477
def filterWildcardGivenBinding (givenPat : Bind ): Boolean =
@@ -1538,7 +1540,7 @@ object desugar {
1538
1540
if useSelectors then Select (Ident (tmpName), nme.selectorName(n))
1539
1541
else Apply (Select (Ident (tmpName), nme.apply), Literal (Constant (n)) :: Nil )
1540
1542
val restDefs =
1541
- for ((( named, tpt), n) <- vars.zipWithIndex if named.name != nme.WILDCARD )
1543
+ for ((named, tpt), n) <- vars.zipWithIndex if named.name != nme.WILDCARD
1542
1544
yield
1543
1545
if mods.is(Lazy ) then
1544
1546
DefDef (named.name.asTermName, Nil , tpt, selector(n))
@@ -2044,33 +2046,36 @@ object desugar {
2044
2046
makeCaseLambda(CaseDef (gen.pat, EmptyTree , body) :: Nil , matchCheckMode)
2045
2047
}
2046
2048
2047
- def hasGivenBind (pat : Tree ): Boolean = pat.existsSubTree {
2048
- case pat @ Bind (_, pat1 ) => pat.mods.is(Given )
2049
+ def hasGivenBind (pat : Tree ): Boolean = pat.existsSubTree:
2050
+ case pat @ Bind (_, _ ) => pat.mods.is(Given )
2049
2051
case _ => false
2050
- }
2051
2052
2052
2053
/** Does this pattern define any given bindings */
2053
2054
def isNestedGivenPattern (pat : Tree ): Boolean = pat match
2054
- case pat @ Bind (_, pat1 ) => hasGivenBind(pat1 )
2055
+ case Bind (_, pat ) => hasGivenBind(pat )
2055
2056
case _ => hasGivenBind(pat)
2056
2057
2057
2058
/** If `pat` is not an Identifier, a Typed(Ident, _), or a Bind, wrap
2058
2059
* it in a Bind with a fresh name. Return the transformed pattern, and the identifier
2059
2060
* that refers to the bound variable for the pattern. Wildcard Binds are
2060
2061
* also replaced by Binds with fresh names.
2061
2062
*/
2062
- def makeIdPat (pat : Tree ): (Tree , Ident ) = pat match {
2063
- case bind @ Bind (name, pat1) =>
2064
- if name == nme.WILDCARD then
2065
- val name = UniqueName .fresh()
2066
- (cpy.Bind (pat)(name, pat1).withMods(bind.mods), Ident (name))
2067
- else (pat, Ident (name))
2063
+ def makeIdPat (pat : Tree ): (Tree , Ident ) = pat match
2064
+ case pat @ Bind (nme.WILDCARD , body) =>
2065
+ val name =
2066
+ body match
2067
+ case Typed (Ident (nme.WILDCARD ), tpt) if pat.mods.is(Given ) => inventGivenName(tpt)
2068
+ case _ => UniqueName .fresh()
2069
+ cpy.Bind (pat)(name, body)
2070
+ .withMods(pat.mods)
2071
+ ->
2072
+ Ident (name)
2073
+ case Bind (name, _) => (pat, Ident (name))
2068
2074
case id : Ident if isVarPattern(id) && id.name != nme.WILDCARD => (id, id)
2069
2075
case Typed (id : Ident , _) if isVarPattern(id) && id.name != nme.WILDCARD => (pat, id)
2070
2076
case _ =>
2071
2077
val name = UniqueName .fresh()
2072
2078
(Bind (name, pat), Ident (name))
2073
- }
2074
2079
2075
2080
/** Make a pattern filter:
2076
2081
* rhs.withFilter { case pat => true case _ => false }
@@ -2128,11 +2133,11 @@ object desugar {
2128
2133
}
2129
2134
}
2130
2135
2131
- /** Is `pat` of the form `x`, `x T`, or `given T`? when used as the lhs of a generator,
2136
+ /** Is `pat` of the form `x`, `x: T`, or `given T`? when used as the lhs of a generator,
2132
2137
* these are all considered irrefutable.
2133
2138
*/
2134
2139
def isVarBinding (pat : Tree ): Boolean = pat match
2135
- case pat @ Bind (_, pat1 ) if pat .mods.is(Given ) => isVarBinding(pat1 )
2140
+ case bind @ Bind (_, pat ) if bind .mods.is(Given ) => isVarBinding(pat )
2136
2141
case IdPattern (_) => true
2137
2142
case _ => false
2138
2143
@@ -2173,36 +2178,42 @@ object desugar {
2173
2178
case (gen : GenFrom ) :: (rest @ (GenFrom (_, _, _) :: _)) =>
2174
2179
val cont = makeFor(mapName, flatMapName, rest, body)
2175
2180
Apply (rhsSelect(gen, flatMapName), makeLambda(gen, cont))
2176
- case (gen : GenFrom ) :: rest
2177
- if sourceVersion.enablesBetterFors
2178
- && rest.dropWhile(_.isInstanceOf [GenAlias ]).headOption.forall(e => e.isInstanceOf [GenFrom ]) // possible aliases followed by a generator or end of for
2179
- && ! rest.takeWhile(_.isInstanceOf [GenAlias ]).exists(a => isNestedGivenPattern(a.asInstanceOf [GenAlias ].pat)) =>
2180
- val cont = makeFor(mapName, flatMapName, rest, body)
2181
- val selectName =
2182
- if rest.exists(_.isInstanceOf [GenFrom ]) then flatMapName
2183
- else mapName
2184
- val aply = Apply (rhsSelect(gen, selectName), makeLambda(gen, cont))
2185
- markTrailingMap(aply, gen, selectName)
2186
- aply
2187
- case (gen : GenFrom ) :: (rest @ GenAlias (_, _) :: _) =>
2188
- val (valeqs, rest1) = rest.span(_.isInstanceOf [GenAlias ])
2189
- val pats = valeqs map { case GenAlias (pat, _) => pat }
2190
- val rhss = valeqs map { case GenAlias (_, rhs) => rhs }
2191
- val (defpat0, id0) = makeIdPat(gen.pat)
2192
- val (defpats, ids) = (pats map makeIdPat).unzip
2193
- val pdefs = valeqs.lazyZip(defpats).lazyZip(rhss).map { (valeq, defpat, rhs) =>
2194
- val mods = defpat match
2195
- case defTree : DefTree => defTree.mods
2196
- case _ => Modifiers ()
2197
- makePatDef(valeq, mods, defpat, rhs)
2198
- }
2199
- val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom (defpat0, gen.expr, gen.checkMode) :: Nil , Block (pdefs, makeTuple(id0 :: ids).withAttachment(ForArtifact , ())))
2200
- val allpats = gen.pat :: pats
2201
- val vfrom1 = GenFrom (makeTuple(allpats), rhs1, GenCheckMode .Ignore )
2202
- makeFor(mapName, flatMapName, vfrom1 :: rest1, body)
2181
+ case (gen : GenFrom ) :: (tail @ GenAlias (_, _) :: _) =>
2182
+ val (valeqs, suffix) = tail.span(_.isInstanceOf [GenAlias ])
2183
+ // possible aliases followed by a generator or end of for, when betterFors.
2184
+ // exclude value definitions with a given pattern (given T = x)
2185
+ val better = sourceVersion.enablesBetterFors
2186
+ && suffix.headOption.forall(_.isInstanceOf [GenFrom ])
2187
+ && ! valeqs.exists(a => isNestedGivenPattern(a.asInstanceOf [GenAlias ].pat))
2188
+ if better then
2189
+ val cont = makeFor(mapName, flatMapName, enums = tail, body)
2190
+ val selectName =
2191
+ if suffix.exists(_.isInstanceOf [GenFrom ]) then flatMapName
2192
+ else mapName
2193
+ Apply (rhsSelect(gen, selectName), makeLambda(gen, cont))
2194
+ .tap(markTrailingMap(_, gen, selectName))
2195
+ else
2196
+ val (pats, rhss) = valeqs.map { case GenAlias (pat, rhs) => (pat, rhs) }.unzip
2197
+ val (defpat0, id0) = makeIdPat(gen.pat)
2198
+ val (defpats, ids) = pats.map(makeIdPat).unzip
2199
+ val pdefs = valeqs.lazyZip(defpats).lazyZip(rhss).map: (valeq, defpat, rhs) =>
2200
+ val mods = defpat match
2201
+ case defTree : DefTree => defTree.mods
2202
+ case _ => Modifiers ()
2203
+ makePatDef(original = valeq, mods, defpat, rhs)
2204
+ val rhs1 =
2205
+ val enums = GenFrom (defpat0, gen.expr, gen.checkMode) :: Nil
2206
+ val body = Block (pdefs, makeTuple(id0 :: ids).withAttachment(ForArtifact , ()))
2207
+ makeFor(nme.map, nme.flatMap, enums, body)
2208
+ val allpats = gen.pat :: pats
2209
+ val vfrom1 = GenFrom (makeTuple(allpats), rhs1, GenCheckMode .Ignore )
2210
+ makeFor(mapName, flatMapName, enums = vfrom1 :: suffix, body)
2211
+ end if
2203
2212
case (gen : GenFrom ) :: test :: rest =>
2204
- val filtered = Apply (rhsSelect(gen, nme.withFilter), makeLambda(gen, test))
2205
- val genFrom = GenFrom (gen.pat, filtered, if sourceVersion.enablesBetterFors then GenCheckMode .Filtered else GenCheckMode .Ignore )
2213
+ val genFrom =
2214
+ val filtered = Apply (rhsSelect(gen, nme.withFilter), makeLambda(gen, test))
2215
+ val mode = if sourceVersion.enablesBetterFors then GenCheckMode .Filtered else GenCheckMode .Ignore
2216
+ GenFrom (gen.pat, filtered, mode)
2206
2217
makeFor(mapName, flatMapName, genFrom :: rest, body)
2207
2218
case GenAlias (_, _) :: _ if sourceVersion.enablesBetterFors =>
2208
2219
val (valeqs, rest) = enums.span(_.isInstanceOf [GenAlias ])
@@ -2213,7 +2224,7 @@ object desugar {
2213
2224
val mods = defpat match
2214
2225
case defTree : DefTree => defTree.mods
2215
2226
case _ => Modifiers ()
2216
- makePatDef(valeq, mods, defpat, rhs)
2227
+ makePatDef(original = valeq, mods, defpat, rhs)
2217
2228
}
2218
2229
Block (pdefs, makeFor(mapName, flatMapName, rest, body))
2219
2230
case _ =>
@@ -2279,7 +2290,7 @@ object desugar {
2279
2290
makeFor(nme.map, nme.flatMap, enums, body) orElse tree
2280
2291
case PatDef (mods, pats, tpt, rhs) =>
2281
2292
val pats1 = if (tpt.isEmpty) pats else pats map (Typed (_, tpt))
2282
- flatTree(pats1 map (makePatDef(tree, mods, _, rhs)))
2293
+ flatTree(pats1. map(makePatDef(original = tree, mods, _, rhs)))
2283
2294
case ext : ExtMethods =>
2284
2295
Block (List (ext), syntheticUnitLiteral.withSpan(ext.span))
2285
2296
case f : FunctionWithMods if f.hasErasedParams => makeFunctionWithValDefs(f, pt)
@@ -2396,7 +2407,7 @@ object desugar {
2396
2407
* without duplicates
2397
2408
*/
2398
2409
private def getVariables (tree : Tree , shouldAddGiven : Context ?=> Bind => Boolean )(using Context ): List [VarInfo ] = {
2399
- val buf = mutable. ListBuffer [VarInfo ]()
2410
+ val buf = ListBuffer .empty [VarInfo ]
2400
2411
def seenName (name : Name ) = buf exists (_._1.name == name)
2401
2412
def add (named : NameTree , t : Tree ): Unit =
2402
2413
if (! seenName(named.name) && named.name.isTermName) buf += ((named, t))
0 commit comments