Skip to content

Commit ad24395

Browse files
committed
Fix #7919: Make sure that quoted.Type does not have unexpected subclasses
Now that quoted.Type and quoted.Expr are not sealed we make them have private constructors to make sure users do not exten them (possibly by mistake).
1 parent 8305bd0 commit ad24395

File tree

8 files changed

+42
-19
lines changed

8 files changed

+42
-19
lines changed

compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import dotty.tools.dotc.tastyreflect.{ReflectionImpl, TastyTreeExpr, TreeType}
1919

2020
import dotty.tools.tasty.TastyString
2121

22-
import scala.internal.quoted._
2322
import scala.reflect.ClassTag
2423

2524
import scala.runtime.quoted.Unpickler._

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import dotty.tools.dotc.ast.tpd.Tree
99
*
1010
* May contain references to code defined outside this TastyTreeExpr instance.
1111
*/
12-
final class TastyTreeExpr(val tree: Tree, val scopeId: Int) extends scala.quoted.Expr[Any] {
12+
final class TastyTreeExpr(val tree: Tree, val scopeId: Int) extends scala.internal.quoted.Expr[Any] {
1313
override def equals(that: Any): Boolean = that match {
1414
case that: TastyTreeExpr =>
1515
// TastyTreeExpr are wrappers around trees, therfore they are equals if their trees are equal.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dotty.tools.dotc.tastyreflect
33
import dotty.tools.dotc.ast.tpd.Tree
44

55
/** An Type backed by a tree */
6-
final class TreeType(val typeTree: Tree, val scopeId: Int) extends scala.quoted.Type[Any] {
6+
final class TreeType(val typeTree: Tree, val scopeId: Int) extends scala.internal.quoted.Type[Any] {
77
override def equals(that: Any): Boolean = that match {
88
case that: TreeType => typeTree ==
99
// TastyTreeExpr are wrappers around trees, therfore they are equals if their trees are equal.

library/src/scala/internal/quoted/Expr.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ package scala.internal.quoted
22

33
import scala.quoted._
44

5+
/** Quoted expression of type `T`
6+
*
7+
* Restriction: only the QuoteContext.tasty.internal implementation is allowed to extend this trait.
8+
* Any other implementation will result in an undefined behavior.
9+
*/
10+
class Expr[+T] extends scala.quoted.Expr[T]
11+
512
object Expr {
613

714
/** Pattern matches an the scrutineeExpr against the patternExpr and returns a tuple
@@ -25,7 +32,7 @@ object Expr {
2532
* @param qctx the current QuoteContext
2633
* @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Expr[Ti]``
2734
*/
28-
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_],
35+
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: scala.quoted.Expr[_])(implicit patternExpr: scala.quoted.Expr[_],
2936
hasTypeSplices: Boolean, qctx: QuoteContext): Option[Tup] = {
3037
import qctx.tasty.{_, given}
3138
new Matcher.QuoteMatcher[qctx.type].termMatch(scrutineeExpr.unseal, patternExpr.unseal, hasTypeSplices).asInstanceOf[Option[Tup]]

library/src/scala/internal/quoted/Type.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ package scala.internal.quoted
22

33
import scala.quoted._
44

5+
/** Quoted type (or kind) `T`
6+
*
7+
* Restriction: only the QuoteContext.tasty.internal implementation is allowed to extend this trait.
8+
* Any other implementation will result in an undefined behavior.
9+
*/
10+
class Type[T <: AnyKind] extends scala.quoted.Type[T]
11+
512
object Type {
613

714
/** Pattern matches an the scrutineeType against the patternType and returns a tuple
@@ -17,7 +24,7 @@ object Type {
1724
* @param qctx the current QuoteContext
1825
* @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Type[Ti]``
1926
*/
20-
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeType: Type[_])(implicit patternType: Type[_],
27+
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeType: scala.quoted.Type[_])(implicit patternType: scala.quoted.Type[_],
2128
hasTypeSplices: Boolean, qctx: QuoteContext): Option[Tup] = {
2229
import qctx.tasty.{_, given}
2330
new Matcher.QuoteMatcher[qctx.type].typeTreeMatch(scrutineeType.unseal, patternType.unseal, hasTypeSplices).asInstanceOf[Option[Tup]]

library/src/scala/quoted/Expr.scala

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@ package scala.quoted
22

33
import scala.quoted.show.SyntaxHighlight
44

5-
/** Quoted expression of type `T`
6-
*
7-
* Restriction: only the QuoteContext.tasty.internal implementation is allowed to extend this trait.
8-
* Any other implementation will result in an undefined behavior.
9-
*/
10-
trait Expr[+T] {
5+
/** Quoted expression of type `T` */
6+
class Expr[+T] private[scala] {
117

128
/** Show a source code like representation of this expression without syntax highlight */
139
def show(implicit qctx: QuoteContext): String = qctx.show(this, SyntaxHighlight.plain)
@@ -57,8 +53,6 @@ trait Expr[+T] {
5753

5854
object Expr {
5955

60-
import scala.internal.quoted._
61-
6256
/** Converts a tuple `(T1, ..., Tn)` to `(Expr[T1], ..., Expr[Tn])` */
6357
type TupleOfExpr[Tup <: Tuple] = Tuple.Map[Tup, [X] =>> (given QuoteContext) => Expr[X]]
6458

library/src/scala/quoted/Type.scala

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@ package scala.quoted
22

33
import scala.quoted.show.SyntaxHighlight
44

5-
/** Quoted type (or kind) `T`
6-
*
7-
* Restriction: only the QuoteContext.tasty.internal implementation is allowed to extend this trait.
8-
* Any other implementation will result in an undefined behavior.
9-
*/
10-
trait Type[T <: AnyKind] {
5+
/** Quoted type (or kind) `T` */
6+
class Type[T <: AnyKind] private[scala] {
117
type `$splice` = T
128

139
/** Show a source code like representation of this type without syntax highlight */

tests/neg/i7919.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import scala.quoted._
2+
3+
object Test {
4+
def staged[T](given qctx: QuoteContext) = {
5+
import qctx.tasty.{_, given}
6+
given typeT: quoted.Type[T] // error
7+
val tTypeTree = typeT.unseal
8+
val tt = typeOf[T]
9+
'{ "in staged" }
10+
}
11+
12+
given Expr[Int] // error
13+
new Expr[Int] // error
14+
class Expr2 extends Expr[Int] // error
15+
16+
given Type[Int] // error
17+
new Type[Int] // error
18+
class Type2 extends Type[Int] // error
19+
20+
}

0 commit comments

Comments
 (0)