@@ -13,13 +13,14 @@ import util.{Property, SourceFile, SourcePosition, SrcPos, Chars}
1313import config .{Feature , Config }
1414import config .Feature .{sourceVersion , migrateTo3 , enabled }
1515import config .SourceVersion .*
16- import collection .mutable
1716import reporting .*
1817import printing .Formatting .hl
1918import config .Printers
2019import parsing .Parsers
20+ import dotty .tools .dotc .util .chaining .*
2121
2222import scala .annotation .{unchecked as _ , * }, internal .sharable
23+ import scala .collection .mutable , mutable .ListBuffer
2324
2425object desugar {
2526 import untpd .*
@@ -272,12 +273,12 @@ object desugar {
272273 */
273274 private def desugarContextBounds (
274275 tdef : TypeDef ,
275- evidenceBuf : mutable. ListBuffer [ValDef ],
276+ evidenceBuf : ListBuffer [ValDef ],
276277 evidenceFlags : FlagSet ,
277278 freshName : untpd.Tree => TermName ,
278279 allParamss : List [ParamClause ])(using Context ): TypeDef =
279280
280- val evidenceNames = mutable. ListBuffer [TermName ]()
281+ val evidenceNames = ListBuffer .empty [TermName ]
281282
282283 def desugarRHS (rhs : Tree ): Tree = rhs match
283284 case ContextBounds (tbounds, ctxbounds) =>
@@ -322,7 +323,7 @@ object desugar {
322323 end desugarContextBounds
323324
324325 def elimContextBounds (meth : Tree , isPrimaryConstructor : Boolean = false )(using Context ): Tree =
325- val evidenceParamBuf = mutable. ListBuffer [ValDef ]()
326+ val evidenceParamBuf = ListBuffer .empty [ValDef ]
326327 var seenContextBounds : Int = 0
327328 def freshName (unused : Tree ) =
328329 seenContextBounds += 1 // Start at 1 like FreshNameCreator.
@@ -647,7 +648,7 @@ object desugar {
647648 * ultimately map to deferred givens.
648649 */
649650 def typeDef (tdef : TypeDef )(using Context ): Tree =
650- val evidenceBuf = new mutable. ListBuffer [ValDef ]
651+ val evidenceBuf = ListBuffer .empty [ValDef ]
651652 val result = desugarContextBounds(
652653 tdef, evidenceBuf,
653654 (tdef.mods.flags.toTermFlags & AccessFlags ) | Lazy | DeferredGivenFlags ,
@@ -1343,7 +1344,7 @@ object desugar {
13431344 )).withSpan(tree.span)
13441345 end makePolyFunctionType
13451346
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`. */
13471348 def inventGivenName (impl : Tree )(using Context ): SimpleName =
13481349 val str = impl match
13491350 case impl : Template =>
@@ -1422,7 +1423,7 @@ object desugar {
14221423 ids.map(expand(_, false ))
14231424 else {
14241425 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))
14261427 }
14271428 }
14281429
@@ -1453,10 +1454,10 @@ object desugar {
14531454 * val/var/lazy val p = e
14541455 *
14551456 * 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))
14571458 *
14581459 * 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))
14601461 * val/var/def x_1 = t$._1
14611462 * ...
14621463 * val/var/def x_N = t$._N
@@ -1470,6 +1471,7 @@ object desugar {
14701471 then cpy.Ident (id)(WildcardParamName .fresh())
14711472 else id
14721473 derivedValDef(original, id1, tpt, rhs, mods)
1474+
14731475 case _ =>
14741476
14751477 def filterWildcardGivenBinding (givenPat : Bind ): Boolean =
@@ -1538,7 +1540,7 @@ object desugar {
15381540 if useSelectors then Select (Ident (tmpName), nme.selectorName(n))
15391541 else Apply (Select (Ident (tmpName), nme.apply), Literal (Constant (n)) :: Nil )
15401542 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
15421544 yield
15431545 if mods.is(Lazy ) then
15441546 DefDef (named.name.asTermName, Nil , tpt, selector(n))
@@ -2044,33 +2046,36 @@ object desugar {
20442046 makeCaseLambda(CaseDef (gen.pat, EmptyTree , body) :: Nil , matchCheckMode)
20452047 }
20462048
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 )
20492051 case _ => false
2050- }
20512052
20522053 /** Does this pattern define any given bindings */
20532054 def isNestedGivenPattern (pat : Tree ): Boolean = pat match
2054- case pat @ Bind (_, pat1 ) => hasGivenBind(pat1 )
2055+ case Bind (_, pat ) => hasGivenBind(pat )
20552056 case _ => hasGivenBind(pat)
20562057
20572058 /** If `pat` is not an Identifier, a Typed(Ident, _), or a Bind, wrap
20582059 * it in a Bind with a fresh name. Return the transformed pattern, and the identifier
20592060 * that refers to the bound variable for the pattern. Wildcard Binds are
20602061 * also replaced by Binds with fresh names.
20612062 */
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))
20682074 case id : Ident if isVarPattern(id) && id.name != nme.WILDCARD => (id, id)
20692075 case Typed (id : Ident , _) if isVarPattern(id) && id.name != nme.WILDCARD => (pat, id)
20702076 case _ =>
20712077 val name = UniqueName .fresh()
20722078 (Bind (name, pat), Ident (name))
2073- }
20742079
20752080 /** Make a pattern filter:
20762081 * rhs.withFilter { case pat => true case _ => false }
@@ -2128,11 +2133,11 @@ object desugar {
21282133 }
21292134 }
21302135
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,
21322137 * these are all considered irrefutable.
21332138 */
21342139 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 )
21362141 case IdPattern (_) => true
21372142 case _ => false
21382143
@@ -2173,36 +2178,42 @@ object desugar {
21732178 case (gen : GenFrom ) :: (rest @ (GenFrom (_, _, _) :: _)) =>
21742179 val cont = makeFor(mapName, flatMapName, rest, body)
21752180 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
22032212 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)
22062217 makeFor(mapName, flatMapName, genFrom :: rest, body)
22072218 case GenAlias (_, _) :: _ if sourceVersion.enablesBetterFors =>
22082219 val (valeqs, rest) = enums.span(_.isInstanceOf [GenAlias ])
@@ -2213,7 +2224,7 @@ object desugar {
22132224 val mods = defpat match
22142225 case defTree : DefTree => defTree.mods
22152226 case _ => Modifiers ()
2216- makePatDef(valeq, mods, defpat, rhs)
2227+ makePatDef(original = valeq, mods, defpat, rhs)
22172228 }
22182229 Block (pdefs, makeFor(mapName, flatMapName, rest, body))
22192230 case _ =>
@@ -2279,7 +2290,7 @@ object desugar {
22792290 makeFor(nme.map, nme.flatMap, enums, body) orElse tree
22802291 case PatDef (mods, pats, tpt, rhs) =>
22812292 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)))
22832294 case ext : ExtMethods =>
22842295 Block (List (ext), syntheticUnitLiteral.withSpan(ext.span))
22852296 case f : FunctionWithMods if f.hasErasedParams => makeFunctionWithValDefs(f, pt)
@@ -2396,7 +2407,7 @@ object desugar {
23962407 * without duplicates
23972408 */
23982409 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 ]
24002411 def seenName (name : Name ) = buf exists (_._1.name == name)
24012412 def add (named : NameTree , t : Tree ): Unit =
24022413 if (! seenName(named.name) && named.name.isTermName) buf += ((named, t))
0 commit comments