Skip to content

Commit 8cff236

Browse files
Make quote pattern type variable order deterministic (#17938)
This changes the order in which the type variables are listed in the encoded quote pattern. The order of the variables is the same as the order as they appear in the source. Example: ```scala import scala.quoted.* def f(x: Expr[Any])(using Quotes) = x match case '{ type t; type u; Map[v, w]() } => ``` ```scala [[syntax trees at end of typer]] package <empty> { import scala.quoted.* final lazy module val Test$package: Test$package = new Test$package() final module class Test$package() extends Object() { this: Test$package.type => def f(x: scala.quoted.Expr[Any])(using x$2: scala.quoted.Quotes): Unit = x match { case x$2.asInstanceOf[scala.quoted.runtime.QuoteMatching].ExprMatch. unapply[ scala.quoted.runtime.QuoteMatching.KCons[t @ _, scala.quoted.runtime.QuoteMatching.KCons[u @ _, scala.quoted.runtime.QuoteMatching.KCons[v @ _, scala.quoted.runtime.QuoteMatching.KCons[w @ _, scala.quoted.runtime.QuoteMatching.KNil] ] ] ], (scala.quoted.Type[t], scala.quoted.Type[u], scala.quoted.Type[v], scala.quoted.Type[w]) ]( Tuple4.unapply[scala.quoted.Type[t], scala.quoted.Type[u], scala.quoted.Type[v], scala.quoted.Type[w]](given t$given1 @ _, given u$given1 @ _, given v$given1 @ _, given w$given1 @ _) )( '{ { @patternType type t >: Nothing <: Any @patternType type u >: Nothing <: Any @patternType type v @patternType type w Map.apply[v, w]([ : (v, w)]*) } }.apply(x$2) ) => () } } } ``` We want all the places where `t`, `u`, `v` and `w` listed in some way to be in that same order.
2 parents 482dfeb + 2db2c11 commit 8cff236

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala

+14-8
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,10 @@ trait QuotesAndSplices {
199199
* )
200200
* ```
201201
*/
202-
private def splitQuotePattern(quoted: Tree)(using Context): (Map[Symbol, Bind], Tree, List[Tree]) = {
202+
private def splitQuotePattern(quoted: Tree)(using Context): (collection.Map[Symbol, Bind], Tree, List[Tree]) = {
203203
val ctx0 = ctx
204204

205-
val typeBindings: collection.mutable.Map[Symbol, Bind] = collection.mutable.Map.empty
205+
val typeBindings: mutable.Map[Symbol, Bind] = mutable.LinkedHashMap.empty
206206
def getBinding(sym: Symbol): Bind =
207207
typeBindings.getOrElseUpdate(sym, {
208208
val bindingBounds = sym.info
@@ -296,13 +296,19 @@ trait QuotesAndSplices {
296296
}
297297
}
298298
val shape0 = splitter.transform(quoted)
299-
val patterns = (splitter.freshTypePatBuf.iterator ++ splitter.typePatBuf.iterator ++ splitter.patBuf.iterator).toList
299+
val patterns = (splitter.typePatBuf.iterator ++ splitter.freshTypePatBuf.iterator ++ splitter.patBuf.iterator).toList
300300
val freshTypeBindings = splitter.freshTypeBindingsBuff.result()
301301

302-
val shape1 = seq(
303-
freshTypeBindings,
304-
shape0
305-
)
302+
val shape1 = shape0 match
303+
case Block(stats @ ((tdef: TypeDef) :: rest), expr) if tdef.symbol.hasAnnotation(defn.QuotedRuntimePatterns_patternTypeAnnot) =>
304+
val (bindings, otherStats) = stats.span {
305+
case tdef: TypeDef => tdef.symbol.hasAnnotation(defn.QuotedRuntimePatterns_patternTypeAnnot)
306+
case _ => true
307+
}
308+
cpy.Block(shape0)(bindings ::: freshTypeBindings ::: otherStats, expr)
309+
case _ =>
310+
seq(freshTypeBindings, shape0)
311+
306312
val shape2 =
307313
if (freshTypeBindings.isEmpty) shape1
308314
else {
@@ -319,7 +325,7 @@ trait QuotesAndSplices {
319325
new TreeTypeMap(typeMap = typeMap).transform(shape1)
320326
}
321327

322-
(typeBindings.toMap, shape2, patterns)
328+
(typeBindings, shape2, patterns)
323329
}
324330

325331
/** Type a quote pattern `case '{ <quoted> } =>` qiven the a current prototype. Typing the pattern

0 commit comments

Comments
 (0)