Skip to content

Commit e6eda5e

Browse files
committed
A patch for nested given definitions
1 parent 15ddef6 commit e6eda5e

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,12 @@ object desugar {
20442044
makeCaseLambda(CaseDef(gen.pat, EmptyTree, body) :: Nil, matchCheckMode)
20452045
}
20462046

2047+
/** Does this pattern define any given bindings */
2048+
def isGivenPattern(pat: Tree): Boolean = pat.existsSubTree {
2049+
case pat @ Bind(_, pat1) => pat.mods.is(Given)
2050+
case _ => false
2051+
}
2052+
20472053
/** If `pat` is not an Identifier, a Typed(Ident, _), or a Bind, wrap
20482054
* it in a Bind with a fresh name. Return the transformed pattern, and the identifier
20492055
* that refers to the bound variable for the pattern. Wildcard Binds are
@@ -2165,7 +2171,8 @@ object desugar {
21652171
Apply(rhsSelect(gen, flatMapName), makeLambda(gen, cont))
21662172
case (gen: GenFrom) :: rest
21672173
if sourceVersion.isAtLeast(`3.7`)
2168-
&& rest.dropWhile(_.isInstanceOf[GenAlias]).headOption.forall(e => e.isInstanceOf[GenFrom]) => // possible aliases followed by a generator or end of for
2174+
&& rest.dropWhile(_.isInstanceOf[GenAlias]).headOption.forall(e => e.isInstanceOf[GenFrom]) // possible aliases followed by a generator or end of for
2175+
&& !rest.takeWhile(_.isInstanceOf[GenAlias]).exists(a => isGivenPattern(a.asInstanceOf[GenAlias].pat)) =>
21692176
val cont = makeFor(mapName, flatMapName, rest, body)
21702177
val selectName =
21712178
if rest.exists(_.isInstanceOf[GenFrom]) then flatMapName

tests/pos/better-fors-given.scala

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
@main def Test: Unit =
2+
for
3+
x <- Option(23 -> "abc")
4+
(a @ given Int, b @ given String) = x
5+
_ <- Option(1)
6+
yield
7+
assert(summon[Int] == 23)
8+
9+
for
10+
x <- Option((1.3, 23 -> "abc"))
11+
(_, (a @ given Int, b @ given String)) = x
12+
_ <- Option(1)
13+
yield
14+
assert(summon[Int] == 23)
15+
16+
for
17+
x <- Option(Some(23 -> "abc"))
18+
Some(a @ given Int, b @ given String) = x
19+
_ <- Option(1)
20+
yield
21+
assert(summon[Int] == 23)
22+
23+
for
24+
x <- Option(Some(23))
25+
Some(a @ given Int) = x
26+
_ <- Option(1)
27+
yield
28+
assert(summon[Int] == 23)
29+
30+
for
31+
x <- Option(23)
32+
a @ given Int = x
33+
yield
34+
assert(summon[Int] == 23)
35+
36+
for
37+
x <- Option(23)
38+
_ @ given Int = x
39+
yield
40+
assert(summon[Int] == 23)
41+
42+
for
43+
x <- Option(23)
44+
given Int = x
45+
yield
46+
assert(summon[Int] == 23)
47+
48+
for
49+
x <- Option(23)
50+
given Int = x
51+
_ <- Option(1)
52+
yield
53+
assert(summon[Int] == 23)
54+
55+
for
56+
a @ given Int <- Option(23)
57+
yield
58+
assert(summon[Int] == 23)
59+
60+
for
61+
_ @ given Int <- Option(23)
62+
yield
63+
assert(summon[Int] == 23)
64+
65+
for
66+
given Int <- Option(23)
67+
yield
68+
assert(summon[Int] == 23)

0 commit comments

Comments
 (0)