@@ -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 .*
@@ -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 =>
@@ -2044,33 +2045,35 @@ object desugar {
20442045 makeCaseLambda(CaseDef (gen.pat, EmptyTree , body) :: Nil , matchCheckMode)
20452046 }
20462047
2047- def hasGivenBind (pat : Tree ): Boolean = pat.existsSubTree {
2048- case pat @ Bind (_, pat1 ) => pat.mods.is(Given )
2048+ def hasGivenBind (pat : Tree ): Boolean = pat.existsSubTree:
2049+ case pat @ Bind (_, _ ) => pat.mods.is(Given )
20492050 case _ => false
2050- }
20512051
20522052 /** Does this pattern define any given bindings */
20532053 def isNestedGivenPattern (pat : Tree ): Boolean = pat match
2054- case pat @ Bind (_, pat1 ) => hasGivenBind(pat1 )
2054+ case Bind (_, pat ) => hasGivenBind(pat )
20552055 case _ => hasGivenBind(pat)
20562056
20572057 /** If `pat` is not an Identifier, a Typed(Ident, _), or a Bind, wrap
20582058 * it in a Bind with a fresh name. Return the transformed pattern, and the identifier
20592059 * that refers to the bound variable for the pattern. Wildcard Binds are
20602060 * also replaced by Binds with fresh names.
20612061 */
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))
2062+ def makeIdPat (pat : Tree ): (Tree , Ident ) = pat match
2063+ case bind @ Bind (nme.WILDCARD , pat) =>
2064+ val name = UniqueName .fresh()
2065+ cpy.Bind (pat)(name, pat)
2066+ .withMods(bind.mods)
2067+ .withSpan(bind.span)
2068+ .withAttachment(PatternVar , ())
2069+ ->
2070+ Ident (name)
2071+ case Bind (name, _) => (pat, Ident (name))
20682072 case id : Ident if isVarPattern(id) && id.name != nme.WILDCARD => (id, id)
20692073 case Typed (id : Ident , _) if isVarPattern(id) && id.name != nme.WILDCARD => (pat, id)
20702074 case _ =>
20712075 val name = UniqueName .fresh()
20722076 (Bind (name, pat), Ident (name))
2073- }
20742077
20752078 /** Make a pattern filter:
20762079 * rhs.withFilter { case pat => true case _ => false }
@@ -2173,36 +2176,44 @@ object desugar {
21732176 case (gen : GenFrom ) :: (rest @ (GenFrom (_, _, _) :: _)) =>
21742177 val cont = makeFor(mapName, flatMapName, rest, body)
21752178 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)
2179+ case (gen : GenFrom ) :: (tail @ GenAlias (_, _) :: _) =>
2180+ val (valeqs, suffix) = tail.span(_.isInstanceOf [GenAlias ])
2181+ // possible aliases followed by a generator or end of for, when betterFors.
2182+ // exclude value definitions with a given pattern (given T = x)
2183+ val better = sourceVersion.enablesBetterFors
2184+ && suffix.headOption.forall(_.isInstanceOf [GenFrom ])
2185+ && ! valeqs.exists(a => isNestedGivenPattern(a.asInstanceOf [GenAlias ].pat))
2186+ if better then
2187+ val cont = makeFor(mapName, flatMapName, enums = tail, body)
2188+ val selectName =
2189+ if suffix.exists(_.isInstanceOf [GenFrom ]) then flatMapName
2190+ else mapName
2191+ Apply (rhsSelect(gen, selectName), makeLambda(gen, cont))
2192+ .tap(markTrailingMap(_, gen, selectName))
2193+ else
2194+ val pats = valeqs.map { case GenAlias (pat, _) => pat }
2195+ val rhss = valeqs.map { case GenAlias (_, rhs) => rhs }
2196+ val (defpat0, id0) = makeIdPat(gen.pat)
2197+ val (defpats, ids) = pats.map(makeIdPat).unzip
2198+ val pdefs = valeqs.lazyZip(defpats).lazyZip(rhss).map { (valeq, defpat, rhs) =>
2199+ val mods = defpat match
2200+ case defTree : DefTree => defTree.mods
2201+ case _ => Modifiers ()
2202+ makePatDef(valeq, mods, defpat, rhs)
2203+ }
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 ])
@@ -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