Skip to content

Commit f787086

Browse files
committed
Merge pull request scala#3475 from densh/topic/holemap-ordering
Fix inconsistent binding in patterns with 10+ holes
2 parents e1402ed + 8994da9 commit f787086

File tree

3 files changed

+26
-20
lines changed

3 files changed

+26
-20
lines changed

src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ trait Placeholders { self: Quasiquotes =>
1717

1818
// Step 1: Transform Scala source with holes into vanilla Scala source
1919

20-
lazy val holeMap = new HoleMap()
2120
lazy val posMap = mutable.ListMap[Position, (Int, Int)]()
2221
lazy val code = {
2322
val sb = new StringBuilder()
@@ -58,25 +57,27 @@ trait Placeholders { self: Quasiquotes =>
5857
sb.toString
5958
}
6059

61-
class HoleMap {
62-
private var underlying = immutable.SortedMap[String, Hole]()
63-
private val accessed = mutable.Set[String]()
60+
object holeMap {
61+
private val underlying = mutable.LinkedHashMap.empty[String, Hole]
62+
private val accessed = mutable.Set.empty[String]
6463
def unused: Set[Name] = (underlying.keys.toSet -- accessed).map(TermName(_))
65-
def contains(key: Name) = underlying.contains(key.toString)
66-
def apply(key: Name) = {
67-
val s = key.toString
68-
accessed += s
69-
underlying(s)
70-
}
71-
def update(key: Name, hole: Hole) = {
64+
def contains(key: Name): Boolean = underlying.contains(key.toString)
65+
def apply(key: Name): Hole = {
66+
val skey = key.toString
67+
val value = underlying(skey)
68+
accessed += skey
69+
value
70+
}
71+
def update(key: Name, hole: Hole) =
7272
underlying += key.toString -> hole
73+
def get(key: Name): Option[Hole] = {
74+
val skey = key.toString
75+
underlying.get(skey).map { v =>
76+
accessed += skey
77+
v
78+
}
7379
}
74-
def get(key: Name) = {
75-
val s = key.toString
76-
accessed += s
77-
underlying.get(s)
78-
}
79-
def toList = underlying.toList
80+
def keysIterator: Iterator[TermName] = underlying.keysIterator.map(TermName(_))
8081
}
8182

8283
// Step 2: Transform vanilla Scala AST into an AST with holes
@@ -179,4 +180,4 @@ trait Placeholders { self: Quasiquotes =>
179180
case _ => None
180181
}
181182
}
182-
}
183+
}

src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ trait Reifiers { self: Quasiquotes =>
2929
/** Map that stores freshly generated names linked to the corresponding names in the reified tree.
3030
* This information is used to reify names created by calls to freshTermName and freshTypeName.
3131
*/
32-
var nameMap = collection.mutable.HashMap.empty[Name, Set[TermName]].withDefault { _ => Set() }
32+
val nameMap = collection.mutable.HashMap.empty[Name, Set[TermName]].withDefault { _ => Set() }
3333

3434
/** Wraps expressions into:
3535
* a block which starts with a sequence of vals that correspond
@@ -71,7 +71,7 @@ trait Reifiers { self: Quasiquotes =>
7171
// q"..$freshdefs; $tree"
7272
SyntacticBlock(freshdefs :+ tree)
7373
} else {
74-
val freevars = holeMap.toList.map { case (name, _) => Ident(name) }
74+
val freevars = holeMap.keysIterator.map(Ident(_)).toList
7575
val isVarPattern = tree match { case Bind(name, Ident(nme.WILDCARD)) => true case _ => false }
7676
val cases =
7777
if(isVarPattern) {

test/files/scalacheck/quasiquotes/TermConstructionProps.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,9 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
291291
val stats2 = List.empty[Tree]
292292
assert(q"{ ..$stats2 }" q"")
293293
}
294+
295+
property("consistent variable order") = test {
296+
val q"$a = $b = $c = $d = $e = $f = $g = $h = $k = $l" = q"a = b = c = d = e = f = g = h = k = l"
297+
assert(a q"a" && b q"b" && c q"c" && d q"d" && e q"e" && g q"g" && h q"h" && k q"k" && l q"l")
298+
}
294299
}

0 commit comments

Comments
 (0)