Skip to content

Commit b07cf89

Browse files
author
Aggelos Biboudis
authored
Merge pull request #6189 from dotty-staging/split-unseal-and-cast
Split quoted.Expr casting from sealing
2 parents 3b5f552 + a70a1f3 commit b07cf89

File tree

30 files changed

+119
-105
lines changed

30 files changed

+119
-105
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,19 +1681,16 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
16811681
// QUOTED SEAL/UNSEAL
16821682
//
16831683

1684-
/** View this expression `Expr[_]` as a `Term` */
1684+
/** View this expression `quoted.Expr[_]` as a `Term` */
16851685
def QuotedExpr_unseal(self: scala.quoted.Expr[_])(implicit ctx: Context): Term =
16861686
PickledQuotes.quotedExprToTree(self)
16871687

1688-
/** View this expression `Type[T]` as a `TypeTree` */
1688+
/** View this expression `quoted.Type[_]` as a `TypeTree` */
16891689
def QuotedType_unseal(self: scala.quoted.Type[_])(implicit ctx: Context): TypeTree =
16901690
PickledQuotes.quotedTypeToTree(self)
16911691

1692-
/** Convert `Term` to an `Expr[T]` and check that it conforms to `T` */
1693-
def QuotedExpr_seal[T](self: Term)(tpe: scala.quoted.Type[T])(implicit ctx: Context): scala.quoted.Expr[T] = {
1694-
1695-
val expectedType = QuotedType_unseal(tpe).tpe
1696-
1692+
/** Convert `Term` to an `quoted.Expr[Any]` */
1693+
def QuotedExpr_seal(self: Term)(implicit ctx: Context): scala.quoted.Expr[Any] = {
16971694
def etaExpand(term: Term): Term = term.tpe.widen match {
16981695
case mtpe: Types.MethodType if !mtpe.isParamDependent =>
16991696
val closureResType = mtpe.resType match {
@@ -1705,20 +1702,25 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
17051702
tpd.Closure(closureMethod, tss => etaExpand(new tpd.TreeOps(term).appliedToArgs(tss.head)))
17061703
case _ => term
17071704
}
1705+
new scala.quoted.Exprs.TastyTreeExpr(etaExpand(self))
1706+
}
17081707

1709-
val expanded = etaExpand(self)
1710-
if (expanded.tpe <:< expectedType) {
1711-
new scala.quoted.Exprs.TastyTreeExpr(expanded).asInstanceOf[scala.quoted.Expr[T]]
1708+
/** Checked cast to a `quoted.Expr[U]` */
1709+
def QuotedExpr_cast[U](self: scala.quoted.Expr[_])(implicit tp: scala.quoted.Type[U], ctx: Context): scala.quoted.Expr[U] = {
1710+
val tree = QuotedExpr_unseal(self)
1711+
val expectedType = QuotedType_unseal(tp).tpe
1712+
if (tree.tpe <:< expectedType) {
1713+
self.asInstanceOf[scala.quoted.Expr[U]]
17121714
} else {
1713-
throw new scala.tasty.TastyTypecheckError(
1714-
s"""Term: ${self.show}
1715+
throw new scala.tasty.reflect.ExprCastError(
1716+
s"""Expr: ${tree.show}
17151717
|did not conform to type: ${expectedType.show}
17161718
|""".stripMargin
17171719
)
17181720
}
17191721
}
17201722

1721-
/** Convert `Type` to an `quoted.Type[T]` */
1723+
/** Convert `Type` to an `quoted.Type[_]` */
17221724
def QuotedType_seal(self: Type)(implicit ctx: Context): scala.quoted.Type[_] = {
17231725
val dummySpan = ctx.owner.span // FIXME
17241726
new scala.quoted.Types.TreeType(tpd.TypeTree(self).withSpan(dummySpan))

library/src-bootstrapped/scala/tasty/reflect/QuotedOps.scala

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,29 @@ package scala.tasty.reflect
44
trait QuotedOps extends Core {
55

66
implicit class QuotedExprAPI[T](expr: scala.quoted.Expr[T]) {
7-
/** View this expression `Expr[T]` as a `Term` */
7+
/** View this expression `quoted.Expr[T]` as a `Term` */
88
def unseal(implicit ctx: Context): Term =
99
kernel.QuotedExpr_unseal(expr)
10+
11+
/** Checked cast to a `quoted.Expr[U]` */
12+
def cast[U: scala.quoted.Type](implicit ctx: Context): scala.quoted.Expr[U] =
13+
kernel.QuotedExpr_cast[U](expr)
1014
}
1115

1216
implicit class QuotedTypeAPI[T <: AnyKind](tpe: scala.quoted.Type[T]) {
13-
/** View this expression `Type[T]` as a `TypeTree` */
17+
/** View this expression `quoted.Type[T]` as a `TypeTree` */
1418
def unseal(implicit ctx: Context): TypeTree =
1519
kernel.QuotedType_unseal(tpe)
1620
}
1721

1822
implicit class TermToQuotedAPI(term: Term) {
19-
/** Convert `Term` to an `Expr[T]` and check that it conforms to `T` */
20-
def seal[T](implicit tpe: scala.quoted.Type[T], ctx: Context): scala.quoted.Expr[T] =
21-
kernel.QuotedExpr_seal(term)(tpe)
23+
/** Convert `Term` to an `quoted.Expr[Any]` */
24+
def seal(implicit ctx: Context): scala.quoted.Expr[Any] =
25+
kernel.QuotedExpr_seal(term)
2226
}
2327

2428
implicit class TypeToQuotedAPI(tpe: Type) {
25-
/** Convert `Type` to an `quoted.Type[T]` */
29+
/** Convert `Type` to an `quoted.Type[_]` */
2630
def seal(implicit ctx: Context): scala.quoted.Type[_] =
2731
kernel.QuotedType_seal(tpe)
2832
}

library/src-bootstrapped/scala/tasty/reflect/utils/TreeUtils.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ trait TreeUtils {
1212
def let(rhs: Term)(body: Ident => Term): Term = {
1313
type T // TODO probably it is better to use the Sealed contruct rather than let the user create their own existential type
1414
implicit val rhsTpe: quoted.Type[T] = rhs.tpe.seal.asInstanceOf[quoted.Type[T]]
15-
val rhsExpr = rhs.seal[T]
15+
val rhsExpr = rhs.seal.cast[T]
1616
val expr = '{
1717
val x = $rhsExpr
1818
${
1919
val id = ('x).unseal.asInstanceOf[Ident]
20-
body(id).seal[Any]
20+
body(id).seal
2121
}
2222
}
2323
expr.unseal

library/src-non-bootstrapped/scala/tasty/reflect/QuotedOps.scala

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,29 @@ package scala.tasty.reflect
44
trait QuotedOps extends Core {
55

66
implicit class QuotedExprAPI[T](expr: scala.quoted.Expr[T]) {
7-
/** View this expression `Expr[T]` as a `Term` */
7+
/** View this expression `quoted.Expr[T]` as a `Term` */
88
def unseal(implicit ctx: Context): Term =
99
kernel.QuotedExpr_unseal(expr)
10+
11+
/** Checked cast to a `quoted.Expr[U]` */
12+
def cast[U: scala.quoted.Type](implicit ctx: Context): scala.quoted.Expr[U] =
13+
kernel.QuotedExpr_cast[U](expr)
1014
}
1115

1216
implicit class QuotedTypeAPI[T](tpe: scala.quoted.Type[T]) {
13-
/** View this expression `Type[T]` as a `TypeTree` */
17+
/** View this expression `quoted.Type[T]` as a `TypeTree` */
1418
def unseal(implicit ctx: Context): TypeTree =
1519
kernel.QuotedType_unseal(tpe)
1620
}
1721

1822
implicit class TermToQuotedAPI(term: Term) {
19-
/** Convert `Term` to an `Expr[T]` and check that it conforms to `T` */
20-
def seal[T](implicit tpe: scala.quoted.Type[T], ctx: Context): scala.quoted.Expr[T] =
21-
kernel.QuotedExpr_seal(term)(tpe)
23+
/** Convert `Term` to an `quoted.Expr[Any]` */
24+
def seal(implicit ctx: Context): scala.quoted.Expr[Any] =
25+
kernel.QuotedExpr_seal(term)
2226
}
2327

2428
implicit class TypeToQuotedAPI(tpe: Type) {
25-
/** Convert `Type` to an `quoted.Type[T]` */
29+
/** Convert `Type` to an `quoted.Type[_]` */
2630
def seal(implicit ctx: Context): scala.quoted.Type[_] =
2731
kernel.QuotedType_seal(tpe)
2832
}

library/src/scala/tasty/TastyTypecheckError.scala

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package scala.tasty.reflect
2+
3+
class ExprCastError(msg: String) extends Throwable(msg)

library/src/scala/tasty/reflect/Kernel.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,16 +1375,20 @@ trait Kernel {
13751375
// QUOTED SEAL/UNSEAL
13761376
//
13771377

1378-
/** View this expression `Expr[_]` as a `Term` */
1378+
/** View this expression `quoted.Expr[_]` as a `Term` */
13791379
def QuotedExpr_unseal(self: scala.quoted.Expr[_])(implicit ctx: Context): Term
13801380

1381-
/** View this expression `Type[T]` as a `TypeTree` */
1381+
/** Checked cast to a `quoted.Expr[U]` */
1382+
def QuotedExpr_cast[U](self: scala.quoted.Expr[_])(implicit tp: scala.quoted.Type[U], ctx: Context): scala.quoted.Expr[U]
1383+
1384+
/** View this expression `quoted.Type[T]` as a `TypeTree` */
13821385
def QuotedType_unseal(self: scala.quoted.Type[_])(implicit ctx: Context): TypeTree
13831386

1384-
/** Convert `Term` to an `Expr[T]` and check that it conforms to `T` */
1385-
def QuotedExpr_seal[T](self: Term)(tpe: scala.quoted.Type[T])(implicit ctx: Context): scala.quoted.Expr[T]
1387+
/** Convert `Term` to an `quoted.Expr[Any]` */
1388+
def QuotedExpr_seal(self: Term)(implicit ctx: Context): scala.quoted.Expr[Any]
1389+
13861390

1387-
/** Convert `Type` to an `quoted.Type[T]` */
1391+
/** Convert `Type` to an `quoted.Type[_]` */
13881392
def QuotedType_seal(self: Type)(implicit ctx: Context): scala.quoted.Type[_]
13891393

13901394
//

tests/neg-with-compiler/i5941/macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ object Lens {
1919

2020
// obj.copy(field = value)
2121
def setterBody(obj: Expr[S], value: Expr[T], field: String): Expr[S] =
22-
Select.overloaded(obj.unseal, "copy", Nil, NamedArg(field, value.unseal) :: Nil).seal[S]
22+
Select.overloaded(obj.unseal, "copy", Nil, NamedArg(field, value.unseal) :: Nil).seal.cast[S]
2323

2424
// exception: getter.unseal.underlyingArgument
2525
getter.unseal match {

tests/neg/tasty-macro-assert-1/quoted_1.scala

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

3535
tree match {
3636
case Inlined(_, Nil, Apply(Select(OpsTree(left), op), right :: Nil)) =>
37-
'{assertTrue(${left.seal[Boolean]})} // Buggy code. To generate the errors
37+
'{assertTrue(${left.seal.cast[Boolean]})} // Buggy code. To generate the errors
3838
case _ =>
3939
'{assertTrue($cond)}
4040
}

tests/neg/tasty-macro-assert-2/quoted_1.scala

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

3535
tree match {
3636
case Inlined(_, Nil, Apply(Select(OpsTree(left), op), right :: Nil)) =>
37-
'{assertTrue(${left.seal[Boolean]})} // Buggy code. To generate the errors
37+
'{assertTrue(${left.seal.cast[Boolean]})} // Buggy code. To generate the errors
3838
case _ =>
3939
'{assertTrue($cond)}
4040
}

0 commit comments

Comments
 (0)