Skip to content

Commit 5f204e6

Browse files
committed
Add reflect.ValOrDefDef
Closes #16960
1 parent 769ca3b commit 5f204e6

File tree

5 files changed

+81
-5
lines changed

5 files changed

+81
-5
lines changed

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

+15
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,21 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
266266
end extension
267267
end ClassDefMethods
268268

269+
type ValOrDefDef = tpd.ValOrDefDef
270+
271+
object ValOrDefDefTypeTest extends TypeTest[Tree, ValOrDefDef]:
272+
def unapply(x: Tree): Option[ValOrDefDef & x.type] = x match
273+
case x: (tpd.ValOrDefDef & x.type) => Some(x)
274+
case _ => None
275+
end ValOrDefDefTypeTest
276+
277+
given ValOrDefDefMethods: ValOrDefDefMethods with
278+
extension (self: ValOrDefDef)
279+
def tpt: TypeTree = self.tpt
280+
def rhs: Option[Term] = optional(self.rhs)
281+
end extension
282+
end ValOrDefDefMethods
283+
269284
type DefDef = tpd.DefDef
270285

271286
object DefDefTypeTest extends TypeTest[Tree, DefDef]:

library/src/scala/quoted/Quotes.scala

+28-5
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
116116
* | +- Export
117117
* | +- Definition --+- ClassDef
118118
* | | +- TypeDef
119-
* | | +- DefDef
120-
* | | +- ValDef
119+
* | | +- ValOrDefDef -+- DefDef
120+
* | | +- ValDef
121121
* | |
122122
* | +- Term --------+- Ref -+- Ident -+- Wildcard
123123
* | | +- Select
@@ -532,10 +532,33 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
532532
end extension
533533
end ClassDefMethods
534534

535+
// ValOrDefDef
536+
537+
/** Tree representing a value or method definition in the source code.
538+
* This includes `def`, `val`, `lazy val`, `var`, `object` and parameter definitions.
539+
*/
540+
type ValOrDefDef <: Definition
541+
542+
/** `TypeTest` that allows testing at runtime in a pattern match if a `Tree` is a `ValOrDefDef` */
543+
given ValOrDefDefTypeTest: TypeTest[Tree, ValOrDefDef]
544+
545+
/** Makes extension methods on `ValOrDefDef` available without any imports */
546+
given ValOrDefDefMethods: ValOrDefDefMethods
547+
548+
/** Extension methods of `ValOrDefDef` */
549+
trait ValOrDefDefMethods:
550+
extension (self: ValOrDefDef)
551+
/** The type tree of this `val` or `def` definition */
552+
def tpt: TypeTree
553+
/** The right-hand side of this `val` or `def` definition */
554+
def rhs: Option[Term]
555+
end extension
556+
end ValOrDefDefMethods
557+
535558
// DefDef
536559

537560
/** Tree representing a method definition in the source code */
538-
type DefDef <: Definition
561+
type DefDef <: ValOrDefDef
539562

540563
/** `TypeTest` that allows testing at runtime in a pattern match if a `Tree` is a `DefDef` */
541564
given DefDefTypeTest: TypeTest[Tree, DefDef]
@@ -611,8 +634,8 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
611634

612635
// ValDef
613636

614-
/** Tree representing a value definition in the source code This includes `val`, `lazy val`, `var`, `object` and parameter definitions. */
615-
type ValDef <: Definition
637+
/** Tree representing a value definition in the source code. This includes `val`, `lazy val`, `var`, `object` and parameter definitions. */
638+
type ValDef <: ValOrDefDef
616639

617640
/** `TypeTest` that allows testing at runtime in a pattern match if a `Tree` is a `ValDef` */
618641
given ValDefTypeTest: TypeTest[Tree, ValDef]

project/MiMaFilters.scala

+8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ object MiMaFilters {
2626
ProblemFilters.exclude[MissingFieldProblem]("scala.runtime.stdLibPatches.language#experimental.into"),
2727
ProblemFilters.exclude[MissingClassProblem]("scala.runtime.stdLibPatches.language$experimental$into$"),
2828
// end of New experimental features in 3.3.X
29+
30+
// New API in 3.4.X
31+
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule.ValOrDefDefTypeTest"),
32+
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule.ValOrDefDefMethods"),
33+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule.ValOrDefDefTypeTest"),
34+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule.ValOrDefDefMethods"),
35+
ProblemFilters.exclude[MissingClassProblem]("scala.quoted.Quotes$reflectModule$ValOrDefDefMethods"),
36+
// New API in 3.4.X
2937
)
3038
val TastyCore: Seq[ProblemFilter] = Seq(
3139
ProblemFilters.exclude[DirectMissingMethodProblem]("dotty.tools.tasty.TastyBuffer.reset"),

tests/pos-macros/i16960/Macro_1.scala

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import scala.quoted.*
2+
3+
inline def myMacro = ${ myMacroImpl }
4+
def myMacroImpl(using Quotes) =
5+
import quotes.reflect.*
6+
7+
val valSym = Symbol.newVal(Symbol.spliceOwner, "foo", TypeRepr.of[Int], Flags.EmptyFlags, Symbol.noSymbol)
8+
val vdef = ValDef(valSym, None)
9+
vdef match
10+
case _: ValDef =>
11+
assert(vdef.tpt.tpe =:= TypeRepr.of[Int])
12+
assert(vdef.rhs == None)
13+
vdef match
14+
case vdef: ValOrDefDef =>
15+
assert(vdef.tpt.tpe =:= TypeRepr.of[Int])
16+
assert(vdef.rhs == None)
17+
18+
val methSym = Symbol.newMethod(Symbol.spliceOwner, "bar", ByNameType(TypeRepr.of[Int]))
19+
val ddef = DefDef(methSym, _ => None)
20+
ddef match
21+
case _: DefDef =>
22+
assert(ddef.tpt.tpe =:= TypeRepr.of[Int])
23+
assert(ddef.rhs == None)
24+
ddef match
25+
case ddef: ValOrDefDef =>
26+
assert(ddef.tpt.tpe =:= TypeRepr.of[Int])
27+
assert(ddef.rhs == None)
28+
29+
'{}

tests/pos-macros/i16960/Test_2.scala

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
def test = myMacro

0 commit comments

Comments
 (0)