@@ -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,38 @@ 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 bind @ Bind (nme.WILDCARD , pat) =>
2065
+ val name =
2066
+ pat match
2067
+ case Typed (Ident (nme.WILDCARD ), tpt) if bind.mods.is(Given ) => inventGivenName(tpt)
2068
+ case _ => UniqueName .fresh()
2069
+ val id = Ident (name)
2070
+ cpy.Bind (pat)(name, pat)
2071
+ .withMods(bind.mods)
2072
+ .withSpan(bind.span)
2073
+ ->
2074
+ id
2075
+ case Bind (name, _) => (pat, Ident (name))
2068
2076
case id : Ident if isVarPattern(id) && id.name != nme.WILDCARD => (id, id)
2069
2077
case Typed (id : Ident , _) if isVarPattern(id) && id.name != nme.WILDCARD => (pat, id)
2070
2078
case _ =>
2071
2079
val name = UniqueName .fresh()
2072
2080
(Bind (name, pat), Ident (name))
2073
- }
2074
2081
2075
2082
/** Make a pattern filter:
2076
2083
* rhs.withFilter { case pat => true case _ => false }
@@ -2128,11 +2135,11 @@ object desugar {
2128
2135
}
2129
2136
}
2130
2137
2131
- /** Is `pat` of the form `x`, `x T`, or `given T`? when used as the lhs of a generator,
2138
+ /** Is `pat` of the form `x`, `x: T`, or `given T`? when used as the lhs of a generator,
2132
2139
* these are all considered irrefutable.
2133
2140
*/
2134
2141
def isVarBinding (pat : Tree ): Boolean = pat match
2135
- case pat @ Bind (_, pat1 ) if pat .mods.is(Given ) => isVarBinding(pat1 )
2142
+ case bind @ Bind (_, pat ) if bind .mods.is(Given ) => isVarBinding(pat )
2136
2143
case IdPattern (_) => true
2137
2144
case _ => false
2138
2145
@@ -2173,36 +2180,42 @@ object desugar {
2173
2180
case (gen : GenFrom ) :: (rest @ (GenFrom (_, _, _) :: _)) =>
2174
2181
val cont = makeFor(mapName, flatMapName, rest, body)
2175
2182
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)
2183
+ case (gen : GenFrom ) :: (tail @ GenAlias (_, _) :: _) =>
2184
+ val (valeqs, suffix) = tail.span(_.isInstanceOf [GenAlias ])
2185
+ // possible aliases followed by a generator or end of for, when betterFors.
2186
+ // exclude value definitions with a given pattern (given T = x)
2187
+ val better = sourceVersion.enablesBetterFors
2188
+ && suffix.headOption.forall(_.isInstanceOf [GenFrom ])
2189
+ && ! valeqs.exists(a => isNestedGivenPattern(a.asInstanceOf [GenAlias ].pat))
2190
+ if better then
2191
+ val cont = makeFor(mapName, flatMapName, enums = tail, body)
2192
+ val selectName =
2193
+ if suffix.exists(_.isInstanceOf [GenFrom ]) then flatMapName
2194
+ else mapName
2195
+ Apply (rhsSelect(gen, selectName), makeLambda(gen, cont))
2196
+ .tap(markTrailingMap(_, gen, selectName))
2197
+ else
2198
+ val (pats, rhss) = valeqs.map { case GenAlias (pat, rhs) => (pat, rhs) }.unzip
2199
+ val (defpat0, id0) = makeIdPat(gen.pat)
2200
+ val (defpats, ids) = pats.map(makeIdPat).unzip
2201
+ val pdefs = valeqs.lazyZip(defpats).lazyZip(rhss).map: (valeq, defpat, rhs) =>
2202
+ val mods = defpat match
2203
+ case defTree : DefTree => defTree.mods
2204
+ case _ => Modifiers ()
2205
+ makePatDef(original = valeq, mods, defpat, rhs)
2206
+ val rhs1 =
2207
+ val enums = GenFrom (defpat0, gen.expr, gen.checkMode) :: Nil
2208
+ val body = Block (pdefs, makeTuple(id0 :: ids).withAttachment(ForArtifact , ()))
2209
+ makeFor(nme.map, nme.flatMap, enums, body)
2210
+ val allpats = gen.pat :: pats
2211
+ val vfrom1 = GenFrom (makeTuple(allpats), rhs1, GenCheckMode .Ignore )
2212
+ makeFor(mapName, flatMapName, enums = vfrom1 :: suffix, body)
2213
+ end if
2203
2214
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 )
2215
+ val genFrom =
2216
+ val filtered = Apply (rhsSelect(gen, nme.withFilter), makeLambda(gen, test))
2217
+ val mode = if sourceVersion.enablesBetterFors then GenCheckMode .Filtered else GenCheckMode .Ignore
2218
+ GenFrom (gen.pat, filtered, mode)
2206
2219
makeFor(mapName, flatMapName, genFrom :: rest, body)
2207
2220
case GenAlias (_, _) :: _ if sourceVersion.enablesBetterFors =>
2208
2221
val (valeqs, rest) = enums.span(_.isInstanceOf [GenAlias ])
@@ -2213,7 +2226,7 @@ object desugar {
2213
2226
val mods = defpat match
2214
2227
case defTree : DefTree => defTree.mods
2215
2228
case _ => Modifiers ()
2216
- makePatDef(valeq, mods, defpat, rhs)
2229
+ makePatDef(original = valeq, mods, defpat, rhs)
2217
2230
}
2218
2231
Block (pdefs, makeFor(mapName, flatMapName, rest, body))
2219
2232
case _ =>
@@ -2279,7 +2292,7 @@ object desugar {
2279
2292
makeFor(nme.map, nme.flatMap, enums, body) orElse tree
2280
2293
case PatDef (mods, pats, tpt, rhs) =>
2281
2294
val pats1 = if (tpt.isEmpty) pats else pats map (Typed (_, tpt))
2282
- flatTree(pats1 map (makePatDef(tree, mods, _, rhs)))
2295
+ flatTree(pats1. map(makePatDef(original = tree, mods, _, rhs)))
2283
2296
case ext : ExtMethods =>
2284
2297
Block (List (ext), syntheticUnitLiteral.withSpan(ext.span))
2285
2298
case f : FunctionWithMods if f.hasErasedParams => makeFunctionWithValDefs(f, pt)
@@ -2396,7 +2409,7 @@ object desugar {
2396
2409
* without duplicates
2397
2410
*/
2398
2411
private def getVariables (tree : Tree , shouldAddGiven : Context ?=> Bind => Boolean )(using Context ): List [VarInfo ] = {
2399
- val buf = mutable. ListBuffer [VarInfo ]()
2412
+ val buf = ListBuffer .empty [VarInfo ]
2400
2413
def seenName (name : Name ) = buf exists (_._1.name == name)
2401
2414
def add (named : NameTree , t : Tree ): Unit =
2402
2415
if (! seenName(named.name) && named.name.isTermName) buf += ((named, t))
0 commit comments