Skip to content

Commit daeed81

Browse files
Merge pull request #13362 from dotty-staging/add-TypedOrTest
Add TypedOrTest as super type of Typed in reflection
2 parents b830af3 + ffbd83d commit daeed81

File tree

6 files changed

+93
-16
lines changed

6 files changed

+93
-16
lines changed

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

+31-1
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
345345
case x: (tpd.SeqLiteral & x.type) => Some(x)
346346
case x: (tpd.Inlined & x.type) => Some(x)
347347
case x: (tpd.NamedArg & x.type) => Some(x)
348+
case x: (tpd.Typed & x.type) =>
349+
TypedTypeTest.unapply(x) // Matches `Typed` but not `TypedOrTest`
348350
case _ => if x.isTerm then Some(x) else None
349351
end TermTypeTest
350352

@@ -669,7 +671,10 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
669671

670672
object TypedTypeTest extends TypeTest[Tree, Typed]:
671673
def unapply(x: Tree): Option[Typed & x.type] = x match
672-
case x: (tpd.Typed & x.type) => Some(x)
674+
case x: (tpd.Typed & x.type) =>
675+
x.expr match
676+
case TermTypeTest(_) => Some(x)
677+
case _ => None
673678
case _ => None
674679
end TypedTypeTest
675680

@@ -689,6 +694,31 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
689694
end extension
690695
end TypedMethods
691696

697+
type TypedOrTest = tpd.Typed
698+
699+
object TypedOrTestTypeTest extends TypeTest[Tree, TypedOrTest]:
700+
def unapply(x: Tree): Option[TypedOrTest & x.type] = x match
701+
case x: (tpd.Typed & x.type) => Some(x)
702+
case _ => None
703+
end TypedOrTestTypeTest
704+
705+
object TypedOrTest extends TypedOrTestModule:
706+
def apply(expr: Term, tpt: TypeTree): Typed =
707+
withDefaultPos(tpd.Typed(xCheckMacroValidExpr(expr), tpt))
708+
def copy(original: Tree)(expr: Term, tpt: TypeTree): Typed =
709+
tpd.cpy.Typed(original)(xCheckMacroValidExpr(expr), tpt)
710+
def unapply(x: Typed): (Term, TypeTree) =
711+
(x.expr, x.tpt)
712+
end TypedOrTest
713+
714+
given TypedOrTestMethods: TypedOrTestMethods with
715+
extension (self: Typed)
716+
def tree: Tree = self.expr
717+
def tpt: TypeTree = self.tpt
718+
end extension
719+
end TypedOrTestMethods
720+
721+
692722
type Assign = tpd.Assign
693723

694724
object AssignTypeTest extends TypeTest[Tree, Assign]:

compiler/src/scala/quoted/runtime/impl/printers/Extractors.scala

+2
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ object Extractors {
176176
this += "Unapply(" += fun += ", " ++= implicits += ", " ++= patterns += ")"
177177
case Alternatives(patterns) =>
178178
this += "Alternatives(" ++= patterns += ")"
179+
case TypedOrTest(tree, tpt) =>
180+
this += "TypedOrTest(" += tree += ", " += tpt += ")"
179181
}
180182

181183
def visitConstant(x: Constant): this.type = x match {

compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala

+7-3
Original file line numberDiff line numberDiff line change
@@ -928,9 +928,13 @@ object SourceCode {
928928
case Alternatives(trees) =>
929929
inParens(printPatterns(trees, " | "))
930930

931-
case Typed(Wildcard(), tpt) =>
932-
this += "_: "
933-
printTypeTree(tpt)
931+
case TypedOrTest(tree1, tpt) =>
932+
tree1 match
933+
case Wildcard() =>
934+
this += "_: "
935+
printTypeTree(tpt)
936+
case _ =>
937+
printPattern(tree1)
934938

935939
case v: Term =>
936940
printTree(v)

library/src/scala/quoted/Quotes.scala

+49-11
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
131131
* | +- Apply
132132
* | +- TypeApply
133133
* | +- Super
134-
* | +- Typed
135134
* | +- Assign
136135
* | +- Block
137136
* | +- Closure
@@ -144,7 +143,15 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
144143
* | +- Inlined
145144
* | +- SelectOuter
146145
* | +- While
146+
* | +---+- Typed
147+
* | /
148+
* +- TypedOrTest +----------------·
149+
* +- Bind
150+
* +- Unapply
151+
* +- Alternatives
147152
* |
153+
* +- CaseDef
154+
* +- TypeCaseDef
148155
* |
149156
* +- TypeTree ----+- Inferred
150157
* | +- TypeIdent
@@ -162,13 +169,6 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
162169
* |
163170
* +- TypeBoundsTree
164171
* +- WildcardTypeTree
165-
* |
166-
* +- CaseDef
167-
* |
168-
* +- TypeCaseDef
169-
* +- Bind
170-
* +- Unapply
171-
* +- Alternatives
172172
*
173173
* +- ParamClause -+- TypeParamClause
174174
* +- TermParamClause
@@ -1135,8 +1135,12 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
11351135
/** `TypeTest` that allows testing at runtime in a pattern match if a `Tree` is a `Typed` */
11361136
given TypedTypeTest: TypeTest[Tree, Typed]
11371137

1138-
/** Tree representing a type ascription `x: T` in the source code */
1139-
type Typed <: Term
1138+
/** Tree representing a type ascription `x: T` in the source code.
1139+
*
1140+
* Also represents a pattern that contains a term `x`.
1141+
* Other `: T` patterns use the more general `TypedOrTest`.
1142+
*/
1143+
type Typed <: Term & TypedOrTest
11401144

11411145
/** Module object of `type Typed` */
11421146
val Typed: TypedModule
@@ -1583,6 +1587,38 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
15831587
end extension
15841588
end WhileMethods
15851589

1590+
/** `TypeTest` that allows testing at runtime in a pattern match if a `Tree` is a `TypedOrTest` */
1591+
given TypedOrTestTypeTest: TypeTest[Tree, TypedOrTest]
1592+
1593+
/** Tree representing a type ascription or type test pattern `x: T` in the source code. */
1594+
type TypedOrTest <: Tree
1595+
1596+
/** Module object of `type TypedOrTest` */
1597+
val TypedOrTest: TypedOrTestModule
1598+
1599+
/** Methods of the module object `val TypedOrTest` */
1600+
trait TypedOrTestModule { this: TypedOrTest.type =>
1601+
1602+
/** Create a type ascription `<x: Tree>: <tpt: TypeTree>` */
1603+
def apply(expr: Tree, tpt: TypeTree): TypedOrTest
1604+
1605+
def copy(original: Tree)(expr: Tree, tpt: TypeTree): TypedOrTest
1606+
1607+
/** Matches `<expr: Tree>: <tpt: TypeTree>` */
1608+
def unapply(x: TypedOrTest): (Tree, TypeTree)
1609+
}
1610+
1611+
/** Makes extension methods on `TypedOrTest` available without any imports */
1612+
given TypedOrTestMethods: TypedOrTestMethods
1613+
1614+
/** Extension methods of `TypedOrTest` */
1615+
trait TypedOrTestMethods:
1616+
extension (self: TypedOrTest)
1617+
def tree: Tree
1618+
def tpt: TypeTree
1619+
end extension
1620+
end TypedOrTestMethods
1621+
15861622
// ----- TypeTrees ------------------------------------------------
15871623

15881624
/** Type tree representing a type written in the source */
@@ -4414,6 +4450,8 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
44144450
Unapply.copy(pattern)(transformTerm(pattern.fun)(owner), transformSubTrees(pattern.implicits)(owner), transformTrees(pattern.patterns)(owner))
44154451
case pattern: Alternatives =>
44164452
Alternatives.copy(pattern)(transformTrees(pattern.patterns)(owner))
4453+
case TypedOrTest(inner, tpt) =>
4454+
TypedOrTest.copy(tree)(transformTree(inner)(owner), transformTypeTree(tpt)(owner))
44174455
}
44184456
}
44194457

@@ -4464,7 +4502,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
44644502
case New(tpt) =>
44654503
New.copy(tree)(transformTypeTree(tpt)(owner))
44664504
case Typed(expr, tpt) =>
4467-
Typed.copy(tree)(/*FIXME #12222: transformTerm(expr)(owner)*/transformTree(expr)(owner).asInstanceOf[Term], transformTypeTree(tpt)(owner))
4505+
Typed.copy(tree)(transformTerm(expr)(owner), transformTypeTree(tpt)(owner))
44684506
case tree: NamedArg =>
44694507
NamedArg.copy(tree)(tree.name, transformTerm(tree.value)(owner))
44704508
case Assign(lhs, rhs) =>

project/MiMaFilters.scala

+3
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@ object MiMaFilters {
1515
exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule#SourceFileMethods.path"),
1616
exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#UnapplyModule.apply"),
1717
exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule#UnapplyModule.apply"),
18+
exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule.TypedOrTestTypeTest"),
19+
exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule.TypedOrTest"),
20+
exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule.TypedOrTestMethods"),
1821
)
1922
}

tests/run-staging/i5161.check

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
run : Some(2)
22
show : scala.Tuple2.apply[scala.Option[scala.Int], scala.Option[scala.Int]](scala.Some.apply[scala.Int](1), scala.Some.apply[scala.Int](1)) match {
3-
case scala.Tuple2((scala.Some(x): scala.Some[scala.Int]), (scala.Some(y): scala.Some[scala.Int])) =>
3+
case scala.Tuple2(scala.Some(x), scala.Some(y)) =>
44
scala.Some.apply[scala.Int](x.+(y))
55
case _ =>
66
scala.None

0 commit comments

Comments
 (0)