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
}

tests/run-with-compiler/i5715/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ object scalatest {
1111
cond.unseal.underlyingArgument match {
1212
case app @ Apply(sel @ Select(lhs, op), rhs :: Nil) =>
1313
val IsSelect(select) = sel
14-
val cond = Apply(Select.copy(select)(lhs, "exists"), rhs :: Nil).seal[Boolean]
14+
val cond = Apply(Select.copy(select)(lhs, "exists"), rhs :: Nil).seal.cast[Boolean]
1515
'{ scala.Predef.assert($cond) }
1616
case _ =>
1717
'{ scala.Predef.assert($cond) }

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ object Lens {
5858
getter.unseal match {
5959
case Function(param :: Nil, Path(o, parts)) if o.symbol == param.symbol =>
6060
'{
61-
val setter = (t: T) => (s: S) => ${ setterBody(('s).unseal, ('t).unseal, parts).seal[S] }
61+
val setter = (t: T) => (s: S) => ${ setterBody(('s).unseal, ('t).unseal, parts).seal.cast[S] }
6262
apply($getter)(setter)
6363
}
6464
case _ =>
@@ -122,9 +122,9 @@ object Iso {
122122

123123
'{
124124
// (p: S) => p._1
125-
val to = (p: S) => ${ Select.unique(('p).unseal, "_1").seal[A] }
125+
val to = (p: S) => ${ Select.unique(('p).unseal, "_1").seal.cast[A] }
126126
// (p: A) => S(p)
127-
val from = (p: A) => ${ Select.overloaded(Ident(companion), "apply", Nil, ('p).unseal :: Nil).seal[S] }
127+
val from = (p: A) => ${ Select.overloaded(Ident(companion), "apply", Nil, ('p).unseal :: Nil).seal.cast[S] }
128128
apply(from)(to)
129129
}
130130
}
@@ -137,7 +137,7 @@ object Iso {
137137
val tpS = typeOf[S]
138138

139139
if (tpS.isSingleton) {
140-
val ident = Ident(tpS.asInstanceOf[TermRef]).seal[S]
140+
val ident = Ident(tpS.asInstanceOf[TermRef]).seal.cast[S]
141141
'{
142142
Iso[S, 1](Function.const($ident))(Function.const(1))
143143
}
@@ -153,7 +153,7 @@ object Iso {
153153
case Type.TypeRef(name, prefix) => Type.TermRef(prefix, name)
154154
}
155155

156-
val obj = Select.overloaded(Ident(companion), "apply", Nil, Nil).seal[S]
156+
val obj = Select.overloaded(Ident(companion), "apply", Nil, Nil).seal.cast[S]
157157

158158
'{
159159
Iso[S, 1](Function.const($obj))(Function.const(1))

tests/run-with-compiler/i6171/Macro_1.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,28 @@ object scalatest {
1818
let(rhs) { right =>
1919
val app = Select.overloaded(left, op, Nil, right :: Nil)
2020
let(app) { result =>
21-
val l = left.seal[Any]
22-
val r = right.seal[Any]
23-
val b = result.seal[Boolean]
21+
val l = left.seal
22+
val r = right.seal
23+
val b = result.seal.cast[Boolean]
2424
val code = '{ scala.Predef.assert($b) }
2525
code.unseal
2626
}
2727
}
28-
}.seal[Unit]
28+
}.seal.cast[Unit]
2929
case Apply(f @ Apply(Select(Apply(qual, lhs :: Nil), op), rhs :: Nil), implicits)
3030
if isImplicitMethodType(f.tpe) =>
3131
let(lhs) { left =>
3232
let(rhs) { right =>
3333
val app = Select.overloaded(Apply(qual, left :: Nil), op, Nil, right :: Nil)
3434
let(Apply(app, implicits)) { result =>
35-
val l = left.seal[Any]
36-
val r = right.seal[Any]
37-
val b = result.seal[Boolean]
35+
val l = left.seal
36+
val r = right.seal
37+
val b = result.seal.cast[Boolean]
3838
val code = '{ scala.Predef.assert($b) }
3939
code.unseal
4040
}
4141
}
42-
}.seal[Unit]
42+
}.seal.cast[Unit]
4343
}
4444
}
4545
}

tests/run-with-compiler/reflect-select-constructor/assert_1.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,28 @@ object scalatest {
1919
let(rhs) { right =>
2020
val app = Select.overloaded(left, op, Nil, right :: Nil)
2121
let(app) { result =>
22-
val l = left.seal[Any]
23-
val r = right.seal[Any]
24-
val b = result.seal[Boolean]
22+
val l = left.seal
23+
val r = right.seal
24+
val b = result.seal.cast[Boolean]
2525
val code = '{ scala.Predef.assert($b) }
2626
code.unseal
2727
}
2828
}
29-
}.seal[Unit]
29+
}.seal.cast[Unit]
3030
case Apply(f @ Apply(Select(Apply(qual, lhs :: Nil), op), rhs :: Nil), implicits)
3131
if isImplicitMethodType(f.tpe) =>
3232
let(lhs) { left =>
3333
let(rhs) { right =>
3434
val app = Select.overloaded(Apply(qual, left :: Nil), op, Nil, right :: Nil)
3535
let(Apply(app, implicits)) { result =>
36-
val l = left.seal[Any]
37-
val r = right.seal[Any]
38-
val b = result.seal[Boolean]
36+
val l = left.seal
37+
val r = right.seal
38+
val b = result.seal.cast[Boolean]
3939
val code = '{ scala.Predef.assert($b) }
4040
code.unseal
4141
}
4242
}
43-
}.seal[Unit]
43+
}.seal.cast[Unit]
4444
}
4545
}
4646

tests/run-with-compiler/reflect-select-copy/assert_1.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@ object scalatest {
1818
let(lhs) { left =>
1919
let(rhs) { right =>
2020
let(Apply(Select.copy(sel)(left, op), right :: Nil)) { result =>
21-
val l = left.seal[Any]
22-
val r = right.seal[Any]
23-
val b = result.seal[Boolean]
21+
val l = left.seal
22+
val r = right.seal
23+
val b = result.seal.cast[Boolean]
2424
val code = '{ scala.Predef.assert(${b}) }
2525
code.unseal
2626
}
2727
}
28-
}.seal[Unit]
28+
}.seal.cast[Unit]
2929
case Apply(f @ Apply(IsSelect(sel @ Select(Apply(qual, lhs :: Nil), op)), rhs :: Nil), implicits)
3030
if isImplicitMethodType(f.tpe) =>
3131
let(lhs) { left =>
3232
let(rhs) { right =>
3333
let(Apply(Apply(Select.copy(sel)(Apply(qual, left :: Nil), op), right :: Nil), implicits)) { result =>
34-
val l = left.seal[Any]
35-
val r = right.seal[Any]
36-
val b = result.seal[Boolean]
34+
val l = left.seal
35+
val r = right.seal
36+
val b = result.seal.cast[Boolean]
3737
val code = '{ scala.Predef.assert(${b}) }
3838
code.unseal
3939
}
4040
}
41-
}.seal[Unit]
41+
}.seal.cast[Unit]
4242
}
4343
}
4444

tests/run-with-compiler/reflect-select-value-class/assert_1.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,28 @@ object scalatest {
1919
let(rhs) { right =>
2020
val app = Select.overloaded(left, op, Nil, right :: Nil)
2121
let(app) { result =>
22-
val l = left.seal[Any]
23-
val r = right.seal[Any]
24-
val b = result.seal[Boolean]
22+
val l = left.seal
23+
val r = right.seal
24+
val b = result.seal.cast[Boolean]
2525
val code = '{ scala.Predef.assert($b) }
2626
code.unseal
2727
}
2828
}
29-
}.seal[Unit]
29+
}.seal.cast[Unit]
3030
case Apply(f @ Apply(Select(Apply(qual, lhs :: Nil), op), rhs :: Nil), implicits)
3131
if isImplicitMethodType(f.tpe) =>
3232
let(lhs) { left =>
3333
let(rhs) { right =>
3434
val app = Select.overloaded(Apply(qual, left :: Nil), op, Nil, right :: Nil)
3535
let(Apply(app, implicits)) { result =>
36-
val l = left.seal[Any]
37-
val r = right.seal[Any]
38-
val b = result.seal[Boolean]
36+
val l = left.seal
37+
val r = right.seal
38+
val b = result.seal.cast[Boolean]
3939
val code = '{ scala.Predef.assert($b) }
4040
code.unseal
4141
}
4242
}
43-
}.seal[Unit]
43+
}.seal.cast[Unit]
4444
}
4545
}
4646

0 commit comments

Comments
 (0)