Skip to content

Commit 01b95f5

Browse files
committed
Add BackquotedDefDef to keep track of backquotes in def names
1 parent 4d8ed93 commit 01b95f5

File tree

8 files changed

+58
-13
lines changed

8 files changed

+58
-13
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,9 @@ object desugar {
206206
* ==>
207207
* inline def f(x: Boolean): Any = (if (x) 1 else ""): Any
208208
*/
209-
private def defDef(meth: DefDef, isPrimaryConstructor: Boolean = false)(implicit ctx: Context): Tree = {
209+
private def defDef(meth0: DefDef, isPrimaryConstructor: Boolean = false)(implicit ctx: Context): Tree = {
210+
val meth = transformQuotedPatternName(meth0)
211+
210212
val DefDef(_, tparams, vparamss, tpt, rhs) = meth
211213
val methName = normalizeName(meth, tpt).asTermName
212214
val mods = meth.mods
@@ -281,6 +283,14 @@ object desugar {
281283
}
282284
}
283285

286+
def transformQuotedPatternName(ddef: DefDef)(implicit ctx: Context): DefDef = {
287+
if (ctx.mode.is(Mode.QuotedPattern) && !ddef.isBackquoted && ddef.name != nme.ANON_FUN && ddef.name.startsWith("$")) {
288+
val name = ddef.name.toString.substring(1).toTermName
289+
val mods = ddef.mods.withAddedAnnotation(New(ref(defn.InternalQuoted_patternBindHoleAnnot.typeRef)).withSpan(ddef.span))
290+
cpy.DefDef(ddef)(name).withMods(mods)
291+
} else ddef
292+
}
293+
284294
// Add all evidence parameters in `params` as implicit parameters to `meth` */
285295
private def addEvidenceParams(meth: DefDef, params: List[ValDef])(implicit ctx: Context): DefDef =
286296
params match {

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,9 @@ object Trees {
361361
def tpt: Tree[T]
362362
def unforcedRhs: LazyTree = unforced
363363
def rhs(implicit ctx: Context): Tree[T] = forceIfLazy
364+
365+
/** Is this a `BackquotedValDef` or `BackquotedDefDef` ? */
366+
def isBackquoted: Boolean = false
364367
}
365368

366369
// ----------- Tree case classes ------------------------------------
@@ -704,9 +707,6 @@ object Trees {
704707
assert(isEmpty || tpt != genericEmptyTree)
705708
def unforced: LazyTree = preRhs
706709
protected def force(x: AnyRef): Unit = preRhs = x
707-
708-
/** Is this a `BackquotedValDef` ? */
709-
def isBackquoted: Boolean = false
710710
}
711711

712712
class BackquotedValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], preRhs: LazyTree)(implicit @constructorOnly src: SourceFile)
@@ -725,6 +725,13 @@ object Trees {
725725
protected def force(x: AnyRef): Unit = preRhs = x
726726
}
727727

728+
class BackquotedDefDef[-T >: Untyped] private[ast] (name: TermName, tparams: List[TypeDef[T]],
729+
vparamss: List[List[ValDef[T]]], tpt: Tree[T], preRhs: LazyTree)(implicit @constructorOnly src: SourceFile)
730+
extends DefDef[T](name, tparams, vparamss, tpt, preRhs) {
731+
override def isBackquoted: Boolean = true
732+
override def productPrefix: String = "BackquotedDefDef"
733+
}
734+
728735
/** mods class name template or
729736
* mods trait name template or
730737
* mods type name = rhs or
@@ -943,6 +950,7 @@ object Trees {
943950
type ValDef = Trees.ValDef[T]
944951
type BackquotedValDef = Trees.BackquotedValDef[T]
945952
type DefDef = Trees.DefDef[T]
953+
type BackquotedDefDef = Trees.BackquotedDefDef[T]
946954
type TypeDef = Trees.TypeDef[T]
947955
type Template = Trees.Template[T]
948956
type Import = Trees.Import[T]
@@ -1142,6 +1150,9 @@ object Trees {
11421150
case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)(sourceFile(tree)))
11431151
}
11441152
def DefDef(tree: Tree)(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit ctx: Context): DefDef = tree match {
1153+
case tree: BackquotedDefDef =>
1154+
if ((name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs)) tree
1155+
else finalize(tree, untpd.BackquotedDefDef(name, tparams, vparamss, tpt, rhs)(sourceFile(tree)))
11451156
case tree: DefDef if (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree
11461157
case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs)(sourceFile(tree)))
11471158
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
323323
def ValDef(name: TermName, tpt: Tree, rhs: LazyTree)(implicit src: SourceFile): ValDef = new ValDef(name, tpt, rhs)
324324
def BackquotedValDef(name: TermName, tpt: Tree, rhs: LazyTree)(implicit src: SourceFile): ValDef = new BackquotedValDef(name, tpt, rhs)
325325
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)
326+
def BackquotedDefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit src: SourceFile): DefDef = new BackquotedDefDef(name, tparams, vparamss, tpt, rhs)
326327
def TypeDef(name: TypeName, rhs: Tree)(implicit src: SourceFile): TypeDef = new TypeDef(name, rhs)
327328
def Template(constr: DefDef, parents: List[Tree], derived: List[Tree], self: ValDef, body: LazyTreeList)(implicit src: SourceFile): Template =
328329
if (derived.isEmpty) new Template(constr, parents, self, body)

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,10 +2418,10 @@ object Parsers {
24182418
else
24192419
(Nil, Method)
24202420
val mods1 = addFlag(mods, flags)
2421-
val name = ident()
2421+
val ident = termIdent()
24222422
val tparams = typeParamClauseOpt(ParamOwner.Def)
24232423
val vparamss = paramClauses() match {
2424-
case rparams :: rparamss if leadingParamss.nonEmpty && !isLeftAssoc(name) =>
2424+
case rparams :: rparamss if leadingParamss.nonEmpty && !isLeftAssoc(ident.name) =>
24252425
rparams :: leadingParamss ::: rparamss
24262426
case rparamss =>
24272427
leadingParamss ::: rparamss
@@ -2451,7 +2451,9 @@ object Parsers {
24512451
accept(EQUALS)
24522452
expr()
24532453
}
2454-
finalizeDef(DefDef(name, tparams, vparamss, tpt, rhs), mods1, start)
2454+
2455+
if (ident.isBackquoted) finalizeDef(BackquotedDefDef(ident.name.asTermName, tparams, vparamss, tpt, rhs), mods1, start)
2456+
else finalizeDef(DefDef(ident.name.asTermName, tparams, vparamss, tpt, rhs), mods1, start)
24552457
}
24562458
}
24572459

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,11 +1974,17 @@ class Typer extends Namer
19741974
val pat1 = if (patType eq patType1) pat else pat.withType(patType1)
19751975
patBuf += pat1
19761976
}
1977-
case vdef: ValDef =>
1978-
if (vdef.symbol.annotations.exists(_.symbol == defn.InternalQuoted_patternBindHoleAnnot)) {
1979-
val tpe = AppliedType(defn.QuotedMatchingBindingType, vdef.tpt.tpe :: Nil)
1980-
val sym = ctx0.newPatternBoundSymbol(vdef.name, tpe, vdef.span)
1981-
patBuf += Bind(sym, untpd.Ident(nme.WILDCARD).withType(tpe)).withSpan(vdef.span)
1977+
case ddef: ValOrDefDef =>
1978+
if (ddef.symbol.annotations.exists(_.symbol == defn.InternalQuoted_patternBindHoleAnnot)) {
1979+
val tpe = ddef.symbol.info match {
1980+
case t: ExprType => t.resType
1981+
case t: PolyType => t.resultType.toFunctionType()
1982+
case t: MethodType => t.toFunctionType()
1983+
case t => t
1984+
}
1985+
val exprTpe = AppliedType(defn.QuotedMatchingBindingType, tpe :: Nil)
1986+
val sym = ctx0.newPatternBoundSymbol(ddef.name, exprTpe, ddef.span)
1987+
patBuf += Bind(sym, untpd.Ident(nme.WILDCARD).withType(exprTpe)).withSpan(ddef.span)
19821988
}
19831989
super.transform(tree)
19841990
case _ =>

library/src/scala/quoted/matching/Binding.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import scala.tasty.Reflection // TODO do not depend on reflection directly
88
* @param name string name of this binding
99
* @param id unique id used for equality
1010
*/
11-
class Binding[-T] private[scala](val name: String, private[Binding] val id: Object) { self =>
11+
class Binding[+T] private[scala](val name: String, private[Binding] val id: Object) { self =>
1212

1313
override def equals(obj: Any): Boolean = obj match {
1414
case obj: Binding[_] => obj.id == id

tests/neg/quotedPatterns-3.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ object Test {
44
y // error: Not found: y
55
case '{ ((`$y`: Int) => 3); 2 } =>
66
y // error: Not found: y
7+
case '{ def `$f`: Int = 8; 2 } =>
8+
f // error: Not found: f
79
case _ =>
810
}
911
}

tests/pos/quotedPatterns.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ object Test {
2222
case '{ (($y: Int) => 1 + y + ($z: Int))(2) } =>
2323
val a: quoted.matching.Binding[Int] = y
2424
z
25+
case '{ def $ff: Int = $z; ff } =>
26+
val a: quoted.matching.Binding[Int] = ff
27+
z
28+
case '{ def $ff(i: Int): Int = $z; 2 } =>
29+
val a: quoted.matching.Binding[Int => Int] = ff
30+
z
31+
case '{ def $ff(i: Int)(j: Int): Int = $z; 2 } =>
32+
val a: quoted.matching.Binding[Int => Int => Int] = ff
33+
z
34+
// FIXME
35+
// case '{ def `$ff`[T](i: T): Int = $z; 2 } =>
36+
// val a: quoted.matching.Binding[[T] => T => Int] = ff // TODO make Binding any-kinded
37+
// z
2538
case _ => '{1}
2639
}
2740
}

0 commit comments

Comments
 (0)