diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index ef8226229a7e..a7586f876435 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1093,6 +1093,11 @@ object desugar { val desugared = tree match { case SymbolLit(str) => Literal(Constant(scala.Symbol(str))) + case Quote(expr) => + if (expr.isType) + TypeApply(ref(defn.QuotedType_applyR), List(expr)) + else + Apply(ref(defn.QuotedExpr_applyR), expr) case InterpolatedString(id, segments) => val strs = segments map { case ts: Thicket => ts.trees.head diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index f42130c04321..fb34ebb255a5 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -908,7 +908,6 @@ object Trees { * so that they selectively retype themselves. Retyping needs a context. */ abstract class TreeCopier { - def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 95c5aa94dd37..1b98992dfbad 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -324,16 +324,6 @@ class Definitions { lazy val throwMethod = enterMethod(OpsPackageClass, nme.THROWkw, MethodType(List(ThrowableType), NothingType)) - /** Method representing a term quote */ - lazy val quoteMethod = enterPolyMethod(OpsPackageClass, nme.QUOTE, 1, - pt => MethodType(pt.paramRefs(0) :: Nil, QuotedExprType.appliedTo(pt.paramRefs(0) :: Nil)), - useCompleter = true) - - /** Method representing a type quote */ - lazy val typeQuoteMethod = enterPolyMethod(OpsPackageClass, nme.TYPE_QUOTE, 1, - pt => QuotedTypeType.appliedTo(pt.paramRefs(0) :: Nil), - useCompleter = true) - lazy val NothingClass: ClassSymbol = enterCompleteClassSymbol( ScalaPackageClass, tpnme.Nothing, AbstractFinal, List(AnyClass.typeRef)) def NothingType = NothingClass.typeRef @@ -630,6 +620,11 @@ class Definitions { lazy val QuotedExprType = ctx.requiredClassRef("scala.quoted.Expr") def QuotedExprClass(implicit ctx: Context) = QuotedExprType.symbol.asClass + lazy val QuotedExprModuleType = ctx.requiredModuleRef("scala.quoted.Expr") + def QuotedExprModule(implicit ctx: Context) = QuotedExprModuleType.symbol + lazy val QuotedExpr_applyR = QuotedExprModule.requiredMethodRef(nme.apply) + def QuotedExpr_apply(implicit ctx: Context) = QuotedExpr_applyR.symbol + lazy val QuotedExpr_spliceR = QuotedExprClass.requiredMethod(nme.UNARY_~) def QuotedExpr_~(implicit ctx: Context) = QuotedExpr_spliceR.symbol lazy val QuotedExpr_runR = QuotedExprClass.requiredMethodRef(nme.run) @@ -644,7 +639,8 @@ class Definitions { lazy val QuotedType_spliceR = QuotedTypeClass.requiredType(tpnme.UNARY_~).typeRef def QuotedType_~ = QuotedType_spliceR.symbol - lazy val QuotedTypeModule = QuotedTypeClass.companionModule + lazy val QuotedTypeModuleType = ctx.requiredModuleRef("scala.quoted.Type") + def QuotedTypeModule(implicit ctx: Context) = QuotedTypeModuleType.symbol lazy val QuotedType_applyR = QuotedTypeModule.requiredMethodRef(nme.apply) def QuotedType_apply(implicit ctx: Context) = QuotedType_applyR.symbol @@ -1183,7 +1179,7 @@ class Definitions { /** Lists core methods that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */ lazy val syntheticCoreMethods = - AnyMethods ++ ObjectMethods ++ List(String_+, throwMethod, quoteMethod, typeQuoteMethod) + AnyMethods ++ ObjectMethods ++ List(String_+, throwMethod) lazy val reservedScalaClassNames: Set[Name] = syntheticScalaClasses.map(_.name).toSet diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 3dc4cd2ca5fc..c273b27bc0a6 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -77,6 +77,7 @@ Standard-Section: "ASTs" TopLevelStat* SELECT possiblySigned_NameRef qual_Term QUALTHIS typeIdent_Tree NEW clsType_Term + THROW throwableExpr_Term NAMEDARG paramName_NameRef arg_Term APPLY Length fn_Term arg_Term* TYPEAPPLY Length fn_Term arg_Type* @@ -225,7 +226,7 @@ Standard Section: "Positions" Assoc* object TastyFormat { final val header = Array(0x5C, 0xA1, 0xAB, 0x1F) - val MajorVersion = 6 + val MajorVersion = 7 val MinorVersion = 0 /** Tags used to serialize names */ @@ -332,12 +333,13 @@ object TastyFormat { final val BYNAMEtype = 84 final val BYNAMEtpt = 85 final val NEW = 86 - final val IMPLICITarg = 87 - final val PRIVATEqualified = 88 - final val PROTECTEDqualified = 89 - final val RECtype = 90 - final val TYPEALIAS = 91 - final val SINGLETONtpt = 92 + final val THROW = 87 + final val IMPLICITarg = 88 + final val PRIVATEqualified = 89 + final val PROTECTEDqualified = 90 + final val RECtype = 91 + final val TYPEALIAS = 92 + final val SINGLETONtpt = 93 // Cat. 4: tag Nat AST @@ -560,6 +562,7 @@ object TastyFormat { case APPLY => "APPLY" case TYPEAPPLY => "TYPEAPPLY" case NEW => "NEW" + case THROW => "THROW" case TYPED => "TYPED" case NAMEDARG => "NAMEDARG" case ASSIGN => "ASSIGN" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index f7d942b4bdad..746b7baad157 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -361,10 +361,15 @@ class TreePickler(pickler: TastyPickler) { pickleTree(qual) } case Apply(fun, args) => - writeByte(APPLY) - withLength { - pickleTree(fun) - args.foreach(pickleTree) + if (fun.symbol eq defn.throwMethod) { + writeByte(THROW) + pickleTree(args.head) + } else { + writeByte(APPLY) + withLength { + pickleTree(fun) + args.foreach(pickleTree) + } } case TypeApply(fun, args) => writeByte(TYPEAPPLY) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 6dca21f68b26..2a5e4b315064 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -974,6 +974,8 @@ class TreeUnpickler(reader: TastyReader, untpd.This(qual).withType(ThisType.raw(tref)) case NEW => New(readTpt()) + case THROW => + Throw(readTerm()) case SINGLETONtpt => SingletonTypeTree(readTerm()) case BYNAMEtpt => diff --git a/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala b/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala index b7ad57f2349f..288d07c30ff3 100644 --- a/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala @@ -60,8 +60,8 @@ class DecompilerPrinter(_ctx: Context) extends RefinedPrinter(_ctx) { } override protected def typeApplyText[T >: Untyped](tree: TypeApply[T]): Text = { - if (tree.symbol eq defn.quoteMethod) "'" - else if (tree.symbol eq defn.typeQuoteMethod) "'[" ~ toTextGlobal(tree.args, ", ") ~ "]" + if (tree.symbol eq defn.QuotedExpr_apply) "'" + else if (tree.symbol eq defn.QuotedType_apply) "'[" ~ toTextGlobal(tree.args, ", ") ~ "]" else super.typeApplyText(tree) } } diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index ae6cb049ef4f..d16fbd962ab1 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -360,7 +360,7 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { * core and splices as arguments. */ private def quotation(body: Tree, quote: Tree)(implicit ctx: Context): Tree = { - val isType = quote.symbol eq defn.typeQuoteMethod + val isType = quote.symbol eq defn.QuotedType_apply if (body.symbol.isSplice) { // simplify `'(~x)` to `x` and then transform it val Select(splice, _) = body @@ -369,8 +369,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { else if (level > 0) { val body1 = nested(isQuote = true).transform(body) // Keep quotes as trees to reduce pickled size and have a Expr.show without pickled quotes - if (isType) ref(defn.typeQuoteMethod).appliedToType(body1.tpe.widen) - else ref(defn.quoteMethod).appliedToType(body1.tpe.widen).appliedTo(body1) + if (isType) ref(defn.QuotedType_apply).appliedToType(body1.tpe.widen) + else ref(defn.QuotedExpr_apply).appliedToType(body1.tpe.widen).appliedTo(body1) } else body match { case body: RefTree if isCaptured(body, level + 1) => diff --git a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala index d8a98309a078..aabd341533e2 100644 --- a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala +++ b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala @@ -175,7 +175,7 @@ class SymUtils(val self: Symbol) extends AnyVal { /** Is symbol a quote operation? */ def isQuote(implicit ctx: Context): Boolean = - self == defn.quoteMethod || self == defn.typeQuoteMethod + self == defn.QuotedExpr_apply || self == defn.QuotedType_apply /** Is symbol a splice operation? */ def isSplice(implicit ctx: Context): Boolean = diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 0c0c43dcc9aa..0e7d6af90acf 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -587,7 +587,7 @@ trait Implicits { self: Typer => } } val tag = bindFreeVars(arg) - if (bindFreeVars.ok) ref(defn.typeQuoteMethod).appliedToType(tag) + if (bindFreeVars.ok) ref(defn.QuotedType_apply).appliedToType(tag) else EmptyTree case _ => EmptyTree diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index fcba55cf99d4..79d2a292fe3a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1106,25 +1106,6 @@ class Typer extends Namer Throw(expr1).withPos(tree.pos) } - def typedQuote(tree: untpd.Quote, pt: Type)(implicit ctx: Context): Tree = track("typedQuote") { - val untpd.Quote(body) = tree - val isType = body.isType - val resultClass = if (isType) defn.QuotedTypeClass else defn.QuotedExprClass - val proto1 = pt.baseType(resultClass) match { - case AppliedType(_, argType :: Nil) => argType - case _ => WildcardType - } - val nestedCtx = ctx.fresh.setTree(tree) - if (isType) { - val body1 = typedType(body, proto1)(nestedCtx) - ref(defn.typeQuoteMethod).appliedToTypeTrees(body1 :: Nil) - } - else { - val body1 = typed(body, proto1)(nestedCtx) - ref(defn.quoteMethod).appliedToType(body1.tpe.widen).appliedTo(body1) - } - } - def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(implicit ctx: Context): SeqLiteral = track("typedSeqLiteral") { val proto1 = pt.elemType match { case NoType => WildcardType @@ -1794,7 +1775,6 @@ class Typer extends Namer case tree: untpd.Super => typedSuper(tree, pt) case tree: untpd.SeqLiteral => typedSeqLiteral(tree, pt) case tree: untpd.Inlined => typedInlined(tree, pt) - case tree: untpd.Quote => typedQuote(tree, pt) case tree: untpd.TypeTree => typedTypeTree(tree, pt) case tree: untpd.SingletonTypeTree => typedSingletonTypeTree(tree) case tree: untpd.AndTypeTree => typedAndTypeTree(tree) diff --git a/library/src/scala/quoted/Expr.scala b/library/src/scala/quoted/Expr.scala index 2032d01a109c..b59a62ce6a97 100644 --- a/library/src/scala/quoted/Expr.scala +++ b/library/src/scala/quoted/Expr.scala @@ -10,6 +10,9 @@ sealed abstract class Expr[T] { } object Expr { + /** A term quote is desugared by the compiler into a call to this method */ + def apply[T](x: T): Expr[T] = + throw new Error("Internal error: this method call should have been replaced by the compiler") implicit class AsFunction[T, U](private val f: Expr[T => U]) extends AnyVal { def apply(x: Expr[T]): Expr[U] = new Exprs.FunctionAppliedTo[T, U](f, x) diff --git a/library/src/scala/quoted/Type.scala b/library/src/scala/quoted/Type.scala index 0b7b2b469165..99457263c79a 100644 --- a/library/src/scala/quoted/Type.scala +++ b/library/src/scala/quoted/Type.scala @@ -10,6 +10,10 @@ sealed abstract class Type[T] { /** Some basic type tags, currently incomplete */ object Type { + /** A term quote is desugared by the compiler into a call to this method */ + def apply[T]: Type[T] = + throw new Error("Internal error: this method call should have been replaced by the compiler") + implicit def UnitTag: Type[Unit] = new TaggedType[Unit] implicit def BooleanTag: Type[Boolean] = new TaggedType[Boolean] implicit def ByteTag: Type[Byte] = new TaggedType[Byte] diff --git a/tests/pos/tasty/definitions.scala b/tests/pos/tasty/definitions.scala index 2a99929fbd74..b8eb1e0e3217 100644 --- a/tests/pos/tasty/definitions.scala +++ b/tests/pos/tasty/definitions.scala @@ -73,6 +73,7 @@ object definitions { case Literal(value: Constant) case This(id: Option[Id]) case New(tpt: TypeTree) + case Throw(expr: Term) case NamedArg(name: TermName, arg: Term) case Apply(fn: Term, args: List[Term]) case TypeApply(fn: Term, args: List[TypeTree])