Skip to content

Commit 4d8ed93

Browse files
committed
Add BackquotedValDef to keep track of backquotes in val names
1 parent 3b152c8 commit 4d8ed93

File tree

7 files changed

+39
-14
lines changed

7 files changed

+39
-14
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ object desugar {
166166
}
167167

168168
def transformQuotedPatternName(vdef: ValDef)(implicit ctx: Context): ValDef = {
169-
if (ctx.mode.is(Mode.QuotedPattern) && vdef.name.startsWith("$")) {
169+
if (ctx.mode.is(Mode.QuotedPattern) && !vdef.isBackquoted && vdef.name.startsWith("$")) {
170170
val name = vdef.name.toString.substring(1).toTermName
171171
val mods = vdef.mods.withAddedAnnotation(New(ref(defn.InternalQuoted_patternBindHoleAnnot.typeRef)).withSpan(vdef.span))
172172
cpy.ValDef(vdef)(name).withMods(mods)

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,15 @@ object Trees {
704704
assert(isEmpty || tpt != genericEmptyTree)
705705
def unforced: LazyTree = preRhs
706706
protected def force(x: AnyRef): Unit = preRhs = x
707+
708+
/** Is this a `BackquotedValDef` ? */
709+
def isBackquoted: Boolean = false
710+
}
711+
712+
class BackquotedValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], preRhs: LazyTree)(implicit @constructorOnly src: SourceFile)
713+
extends ValDef[T](name, tpt, preRhs) {
714+
override def isBackquoted: Boolean = true
715+
override def productPrefix: String = "BackquotedValDef"
707716
}
708717

709718
/** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */
@@ -932,6 +941,7 @@ object Trees {
932941
type Alternative = Trees.Alternative[T]
933942
type UnApply = Trees.UnApply[T]
934943
type ValDef = Trees.ValDef[T]
944+
type BackquotedValDef = Trees.BackquotedValDef[T]
935945
type DefDef = Trees.DefDef[T]
936946
type TypeDef = Trees.TypeDef[T]
937947
type Template = Trees.Template[T]
@@ -1125,6 +1135,9 @@ object Trees {
11251135
case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns)(sourceFile(tree)))
11261136
}
11271137
def ValDef(tree: Tree)(name: TermName, tpt: Tree, rhs: LazyTree)(implicit ctx: Context): ValDef = tree match {
1138+
case tree: BackquotedValDef =>
1139+
if ((name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs)) tree
1140+
else finalize(tree, untpd.BackquotedValDef(name, tpt, rhs)(sourceFile(tree)))
11281141
case tree: ValDef if (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree
11291142
case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)(sourceFile(tree)))
11301143
}

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
321321
def Alternative(trees: List[Tree])(implicit src: SourceFile): Alternative = new Alternative(trees)
322322
def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit src: SourceFile): UnApply = new UnApply(fun, implicits, patterns)
323323
def ValDef(name: TermName, tpt: Tree, rhs: LazyTree)(implicit src: SourceFile): ValDef = new ValDef(name, tpt, rhs)
324+
def BackquotedValDef(name: TermName, tpt: Tree, rhs: LazyTree)(implicit src: SourceFile): ValDef = new BackquotedValDef(name, tpt, rhs)
324325
def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit src: SourceFile): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs)
325326
def TypeDef(name: TypeName, rhs: Tree)(implicit src: SourceFile): TypeDef = new TypeDef(name, rhs)
326327
def Template(constr: DefDef, parents: List[Tree], derived: List[Tree], self: ValDef, body: LazyTreeList)(implicit src: SourceFile): Template =
@@ -406,8 +407,12 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
406407
def makeAndType(left: Tree, right: Tree)(implicit ctx: Context): AppliedTypeTree =
407408
AppliedTypeTree(ref(defn.andType.typeRef), left :: right :: Nil)
408409

409-
def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers = EmptyModifiers)(implicit ctx: Context): ValDef =
410-
ValDef(pname, tpe, EmptyTree).withMods(mods | Param)
410+
def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers = EmptyModifiers, isBackquoted: Boolean = false)(implicit ctx: Context): ValDef = {
411+
val vdef =
412+
if (isBackquoted) BackquotedValDef(pname, tpe, EmptyTree)
413+
else ValDef(pname, tpe, EmptyTree)
414+
vdef.withMods(mods | Param)
415+
}
411416

412417
def makeSyntheticParameter(n: Int = 1, tpt: Tree = null, flags: FlagSet = EmptyFlags)(implicit ctx: Context): ValDef =
413418
ValDef(nme.syntheticParamName(n), if (tpt == null) TypeTree() else tpt, EmptyTree)

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,10 @@ object Parsers {
406406
/** Convert tree to formal parameter
407407
*/
408408
def convertToParam(tree: Tree, expected: String = "formal parameter"): ValDef = tree match {
409-
case Ident(name) =>
410-
makeParameter(name.asTermName, TypeTree()).withSpan(tree.span)
411-
case Typed(Ident(name), tpt) =>
412-
makeParameter(name.asTermName, tpt).withSpan(tree.span)
409+
case id @ Ident(name) =>
410+
makeParameter(name.asTermName, TypeTree(), isBackquoted = id.isBackquoted).withSpan(tree.span)
411+
case Typed(id @ Ident(name), tpt) =>
412+
makeParameter(name.asTermName, tpt, isBackquoted = id.isBackquoted).withSpan(tree.span)
413413
case Typed(Splice(Ident(name)), tpt) =>
414414
makeParameter(("$" + name).toTermName, tpt).withSpan(tree.span)
415415
case _ =>
@@ -2372,7 +2372,9 @@ object Parsers {
23722372
}
23732373
} else EmptyTree
23742374
lhs match {
2375-
case (id @ Ident(name: TermName)) :: Nil => {
2375+
case (id: BackquotedIdent) :: Nil if id.name.isTermName =>
2376+
finalizeDef(BackquotedValDef(id.name.asTermName, tpt, rhs), mods, start)
2377+
case Ident(name: TermName) :: Nil => {
23762378
finalizeDef(ValDef(name, tpt, rhs), mods, start)
23772379
} case _ =>
23782380
PatDef(mods, lhs, tpt, rhs)

tests/neg/quotedPatterns-2.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
object Test {
22
def test(x: quoted.Expr[Int]) given tasty.Reflection = x match {
3-
// case '{ val a = 4; '{ a }; $y } => y // error: access to value a from wrong staging level
4-
case '{ val `$y`: Int = 2; 1 } =>
5-
y // error
6-
case '{ ((`$y`: Int) => 3); 2 } =>
7-
y // error
3+
case '{ val a = 4; '{ a }; $y } => y // error: access to value a from wrong staging level
84
case _ =>
95
}
106
}

tests/neg/quotedPatterns-3.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object Test {
2+
def test(x: quoted.Expr[Int]) given tasty.Reflection = x match {
3+
case '{ val `$y`: Int = 2; 1 } =>
4+
y // error: Not found: y
5+
case '{ ((`$y`: Int) => 3); 2 } =>
6+
y // error: Not found: y
7+
case _ =>
8+
}
9+
}

tests/run-with-compiler/quote-matcher-symantics-2/quoted_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ object Macros {
3434
}
3535

3636
def liftFun(e: Expr[DSL => DSL])(implicit env: Map[Binding[DSL], Expr[T]]): Expr[T => T] = e match {
37-
case '{ (`$x`: DSL) => ($body: DSL) } =>
37+
case '{ ($x: DSL) => ($body: DSL) } =>
3838
sym.lam((y: Expr[T]) => lift(body)(env + (x -> y)))
3939

4040
case _ =>

0 commit comments

Comments
 (0)