From 1c19629e373e781523ffc41caa66315b1c705b47 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 27 Jul 2020 17:06:52 +0200 Subject: [PATCH 1/8] Move Staging phase after typer --- compiler/src/dotty/tools/dotc/Compiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 84e81801a495..ecbda7e157ca 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -38,10 +38,10 @@ class Compiler { protected def frontendPhases: List[List[Phase]] = List(new FrontEnd) :: // Compiler frontend: scanner, parser, namer, typer List(new YCheckPositions) :: // YCheck positions - List(new Staging) :: // Check PCP, heal quoted types and expand macros List(new sbt.ExtractDependencies) :: // Sends information on classes' dependencies to sbt via callbacks List(new semanticdb.ExtractSemanticDB) :: // Extract info into .semanticdb files List(new PostTyper) :: // Additional checks and cleanups after type checking + List(new Staging) :: // Check PCP, heal quoted types and expand macros List(new sbt.ExtractAPI) :: // Sends a representation of the API of classes to sbt via callbacks List(new SetRootTree) :: // Set the `rootTreeOrProvider` on class symbols Nil From 7d2c1cc9ef23bd9d1fab14706b263c8fdd4f8e49 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 27 Jul 2020 17:20:58 +0200 Subject: [PATCH 2/8] Detect all quotes in postyper * Explicit * Synthesized implicits * Inlined --- compiler/src/dotty/tools/dotc/transform/PostTyper.scala | 2 ++ compiler/src/dotty/tools/dotc/typer/Inliner.scala | 9 ++------- .../src/dotty/tools/dotc/typer/QuotesAndSplices.scala | 3 --- compiler/src/dotty/tools/dotc/typer/Synthesizer.scala | 2 -- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index ad14b9e7b1d7..84c98c74a815 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -269,6 +269,8 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase val patterns1 = transform(patterns) cpy.UnApply(tree)(transform(fun), transform(implicits), patterns1) case tree: TypeApply => + if tree.symbol.isQuote then + ctx.compilationUnit.needsStaging = true val tree1 @ TypeApply(fn, args) = normalizeTypeArgs(tree) args.foreach(checkInferredWellFormed) if (fn.symbol != defn.ChildAnnot.primaryConstructor) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 93d975d14ec5..304545fe7ac4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -1192,7 +1192,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { } override def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree = - checkStaging(tryInline(tree.asInstanceOf[tpd.Tree]) `orElse` super.typedIdent(tree, pt)) + tryInline(tree.asInstanceOf[tpd.Tree]) `orElse` super.typedIdent(tree, pt) override def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = { assert(tree.hasType, tree) @@ -1204,14 +1204,9 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { else val res = resMaybeReduced ensureAccessible(res.tpe, tree.qualifier.isInstanceOf[untpd.Super], tree.sourcePos) - checkStaging(res) + res } - private def checkStaging(tree: Tree): tree.type = - if tree.symbol.isQuote then - ctx.compilationUnit.needsStaging = true - tree - override def typedIf(tree: untpd.If, pt: Type)(using Context): Tree = typed(tree.cond, defn.BooleanType) match { case cond1 @ ConstantValue(b: Boolean) => diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index 4f4d3f71b3aa..14a65f507aa6 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -40,7 +40,6 @@ trait QuotesAndSplices { */ def typedQuote(tree: untpd.Quote, pt: Type)(using Context): Tree = { record("typedQuote") - ctx.compilationUnit.needsStaging = true tree.quoted match { case untpd.Splice(innerExpr) if tree.isTerm => report.warning("Canceled splice directly inside a quote. '{ ${ XYZ } } is equivalent to XYZ.", tree.sourcePos) @@ -68,7 +67,6 @@ trait QuotesAndSplices { /** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */ def typedSplice(tree: untpd.Splice, pt: Type)(using Context): Tree = { record("typedSplice") - ctx.compilationUnit.needsStaging = true checkSpliceOutsideQuote(tree) tree.expr match { case untpd.Quote(innerExpr) if innerExpr.isTerm => @@ -147,7 +145,6 @@ trait QuotesAndSplices { /** Translate ${ t: Type[T] }` into type `t.splice` while tracking the quotation level in the context */ def typedTypSplice(tree: untpd.TypSplice, pt: Type)(using Context): Tree = { record("typedTypSplice") - ctx.compilationUnit.needsStaging = true checkSpliceOutsideQuote(tree) tree.expr match { case untpd.Quote(innerType) if innerType.isType => diff --git a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala index cf434da334e2..80af11f2e72b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -53,8 +53,6 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): */ val synthesizedTypeTag: SpecialHandler = (formal, span) => def quotedType(t: Type) = - if StagingContext.level == 0 then - ctx.compilationUnit.needsStaging = true // We will need to run ReifyQuotes val qctx = ctx.typer.inferImplicitArg(defn.QuoteContextClass.typeRef, span) qctx.tpe match case tpe: Implicits.SearchFailureType => report.error(tpe.msg, ctx.source.atSpan(span)) From 6c1edfad08fa93afb9941b95271916ac351a4ef9 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 27 Jul 2020 17:31:38 +0200 Subject: [PATCH 3/8] Add quoted.Type.apply constructor Just as `$t` is equivalent to `t.T`, `'[T]` is equivalent to `Type[T]` --- compiler/src/dotty/tools/dotc/ast/TreeInfo.scala | 2 +- compiler/src/dotty/tools/dotc/core/Definitions.scala | 2 +- .../src/dotty/tools/dotc/printing/DecompilerPrinter.scala | 2 +- compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala | 2 +- compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala | 4 ++-- compiler/src/dotty/tools/dotc/transform/Splicer.scala | 4 ++-- compiler/src/dotty/tools/dotc/transform/SymUtils.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 2 +- compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala | 4 ++-- compiler/src/dotty/tools/dotc/typer/Synthesizer.scala | 2 +- .../src-bootstrapped/scala/internal/quoted/CompileTime.scala | 4 ---- library/src-bootstrapped/scala/quoted/Type.scala | 5 +++++ 12 files changed, 18 insertions(+), 17 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 67ba61d4a444..4a97e8273e17 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -397,7 +397,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => case New(_) | Closure(_, _, _) => Pure case TypeApply(fn, _) => - if (fn.symbol.is(Erased) || fn.symbol == defn.InternalQuoted_typeQuote || fn.symbol == defn.Predef_classOf) Pure else exprPurity(fn) + if (fn.symbol.is(Erased) || fn.symbol == defn.QuotedTypeModule_apply || fn.symbol == defn.Predef_classOf) Pure else exprPurity(fn) case Apply(fn, args) => def isKnownPureOp(sym: Symbol) = sym.owner.isPrimitiveValueClass diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 1f7b51bf78e7..1f8a5786aeb1 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -693,7 +693,6 @@ class Definitions { @tu lazy val InternalQuoted_exprQuote : Symbol = InternalQuotedModule.requiredMethod("exprQuote") @tu lazy val InternalQuoted_exprSplice : Symbol = InternalQuotedModule.requiredMethod("exprSplice") @tu lazy val InternalQuoted_exprNestedSplice : Symbol = InternalQuotedModule.requiredMethod("exprNestedSplice") - @tu lazy val InternalQuoted_typeQuote : Symbol = InternalQuotedModule.requiredMethod("typeQuote") @tu lazy val InternalQuoted_QuoteTypeTagAnnot: ClassSymbol = InternalQuotedModule.requiredClass("quoteTypeTag") @tu lazy val InternalQuotedMatcher: Symbol = requiredModule("scala.internal.quoted.Matcher") @@ -713,6 +712,7 @@ class Definitions { @tu lazy val QuotedType_splice: Symbol = QuotedTypeClass.requiredType(tpnme.spliceType) @tu lazy val QuotedTypeModule: Symbol = QuotedTypeClass.companionModule + @tu lazy val QuotedTypeModule_apply: Symbol = QuotedTypeModule.requiredMethod("apply") @tu lazy val TastyReflectionClass: ClassSymbol = requiredClass("scala.tasty.Reflection") diff --git a/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala b/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala index d2ac15493864..d5c75502ceee 100644 --- a/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala @@ -75,6 +75,6 @@ class DecompilerPrinter(_ctx: Context) extends RefinedPrinter(_ctx) { override protected def typeApplyText[T >: Untyped](tree: TypeApply[T]): Text = if (tree.symbol eq defn.InternalQuoted_exprQuote) "'" - else if (tree.symbol eq defn.InternalQuoted_typeQuote) "'[" ~ toTextGlobal(tree.args, ", ") ~ "]" + else if (tree.symbol eq defn.QuotedTypeModule_apply) "'[" ~ toTextGlobal(tree.args, ", ") ~ "]" else super.typeApplyText(tree) } diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 147a959dbedf..e36504b54cbc 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -266,7 +266,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { ("{" ~ toText(trees, "\n") ~ "}").close protected def typeApplyText[T >: Untyped](tree: TypeApply[T]): Text = { - val isQuote = !printDebug && tree.fun.hasType && tree.fun.symbol == defn.InternalQuoted_typeQuote + val isQuote = !printDebug && tree.fun.hasType && tree.fun.symbol == defn.QuotedTypeModule_apply val (open, close) = if (isQuote) (keywordStr("'["), keywordStr("]")) else ("[", "]") val funText = toTextLocal(tree.fun).provided(!isQuote) tree.fun match { diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index 0b2d1cf03520..9bc1e4bcb5ea 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -127,7 +127,7 @@ class ReifyQuotes extends MacroTransform { * core and splices as arguments. */ override protected def transformQuotation(body: Tree, quote: Tree)(using Context): Tree = { - val isType = quote.symbol eq defn.InternalQuoted_typeQuote + val isType = quote.symbol eq defn.QuotedTypeModule_apply if (level > 0) { val body1 = nested(isQuote = true).transform(body)(using quoteContext) super.transformQuotation(body1, quote) @@ -364,7 +364,7 @@ class ReifyQuotes extends MacroTransform { transform(tree)(using ctx.withSource(tree.source)) else reporting.trace(i"Reifier.transform $tree at $level", show = true) { tree match { - case Apply(Select(TypeApply(fn, (body: RefTree) :: Nil), _), _) if fn.symbol == defn.InternalQuoted_typeQuote && isCaptured(body.symbol, level + 1) => + case Apply(Select(TypeApply(fn, (body: RefTree) :: Nil), _), _) if fn.symbol == defn.QuotedTypeModule_apply && isCaptured(body.symbol, level + 1) => // Optimization: avoid the full conversion when capturing `x` // in '{ x } to '{ ${x$1} } and go directly to `x$1` capturers(body.symbol)(body) diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 76b1f6141707..c9d72de172bf 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -141,7 +141,7 @@ object Splicer { case Apply(Select(Apply(fn, quoted :: Nil), nme.apply), _) if fn.symbol == defn.InternalQuoted_exprQuote => // OK - case TypeApply(fn, quoted :: Nil) if fn.symbol == defn.InternalQuoted_typeQuote => + case TypeApply(fn, quoted :: Nil) if fn.symbol == defn.QuotedTypeModule_apply => // OK case Literal(Constant(value)) => @@ -231,7 +231,7 @@ object Splicer { } interpretQuote(quoted1) - case Apply(Select(TypeApply(fn, quoted :: Nil), _), _) if fn.symbol == defn.InternalQuoted_typeQuote => + case Apply(Select(TypeApply(fn, quoted :: Nil), _), _) if fn.symbol == defn.QuotedTypeModule_apply => interpretTypeQuote(quoted) case Literal(Constant(value)) => diff --git a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala index 28395538d825..c9373622bf91 100644 --- a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala +++ b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala @@ -203,7 +203,7 @@ object SymUtils { /** Is symbol a quote operation? */ def isQuote(using Context): Boolean = - self == defn.InternalQuoted_exprQuote || self == defn.InternalQuoted_typeQuote + self == defn.InternalQuoted_exprQuote || self == defn.QuotedTypeModule_apply /** Is symbol a term splice operation? */ def isExprSplice(using Context): Boolean = diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 304545fe7ac4..0bb431a1479a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -528,7 +528,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { case New(_) | Closure(_, _, _) => true case TypeApply(fn, _) => - if (fn.symbol.is(Erased) || fn.symbol == defn.InternalQuoted_typeQuote) true else apply(fn) + if (fn.symbol.is(Erased) || fn.symbol == defn.QuotedTypeModule_apply) true else apply(fn) case Apply(fn, args) => def isKnownPureOp(sym: Symbol) = sym.owner.isPrimitiveValueClass diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index 14a65f507aa6..122d77056ece 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -58,7 +58,7 @@ trait QuotesAndSplices { if ctx.mode.is(Mode.Pattern) then typedQuotePattern(tree, pt, qctx) else if (tree.quoted.isType) - typedTypeApply(untpd.TypeApply(untpd.ref(defn.InternalQuoted_typeQuote.termRef), tree.quoted :: Nil), pt)(using quoteContext).select(nme.apply).appliedTo(qctx) + typedTypeApply(untpd.TypeApply(untpd.ref(defn.QuotedTypeModule_apply.termRef), tree.quoted :: Nil), pt)(using quoteContext).select(nme.apply).appliedTo(qctx) else typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprQuote.termRef), tree.quoted), pt)(using pushQuoteContext(qctx)).select(nme.apply).appliedTo(qctx) tree1.withSpan(tree.span) @@ -439,7 +439,7 @@ trait QuotesAndSplices { val quoteClass = if (tree.quoted.isTerm) defn.QuotedExprClass else defn.QuotedTypeClass val quotedPattern = if (tree.quoted.isTerm) ref(defn.InternalQuoted_exprQuote.termRef).appliedToType(defn.AnyType).appliedTo(shape).select(nme.apply).appliedTo(qctx) - else ref(defn.InternalQuoted_typeQuote.termRef).appliedToTypeTree(shape).select(nme.apply).appliedTo(qctx) + else ref(defn.QuotedTypeModule_apply.termRef).appliedToTypeTree(shape).select(nme.apply).appliedTo(qctx) UnApply( fun = ref(unapplySym.termRef).appliedToTypeTrees(typeBindingsTuple :: TypeTree(patType) :: Nil), implicits = quotedPattern :: Literal(Constant(typeBindings.nonEmpty)) :: qctx :: Nil, diff --git a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala index 80af11f2e72b..1215df0a97a3 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -57,7 +57,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): qctx.tpe match case tpe: Implicits.SearchFailureType => report.error(tpe.msg, ctx.source.atSpan(span)) case _ => - ref(defn.InternalQuoted_typeQuote).appliedToType(t).select(nme.apply).appliedTo(qctx) + ref(defn.QuotedTypeModule_apply).appliedToType(t).select(nme.apply).appliedTo(qctx) formal.argInfos match case arg :: Nil => val deepDealias = new TypeMap: diff --git a/library/src-bootstrapped/scala/internal/quoted/CompileTime.scala b/library/src-bootstrapped/scala/internal/quoted/CompileTime.scala index 4891d3cbf8c8..e6e6972481d5 100644 --- a/library/src-bootstrapped/scala/internal/quoted/CompileTime.scala +++ b/library/src-bootstrapped/scala/internal/quoted/CompileTime.scala @@ -20,10 +20,6 @@ object CompileTime { @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.exprNestedSplice`") def exprNestedSplice[T](ctx: QuoteContext)(x: ctx.Nested ?=> Expr[T]): T = ??? - /** A type quote is desugared by the compiler into a call to this method */ - @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.typeQuote`") - def typeQuote[T <: AnyKind]: QuoteContext ?=> Type[T] = ??? - /** Artifact of pickled type splices * * During quote reification a quote `'{ ... F[$t] ... }` will be transformed into diff --git a/library/src-bootstrapped/scala/quoted/Type.scala b/library/src-bootstrapped/scala/quoted/Type.scala index 4a25af61f543..7b5b097954c8 100644 --- a/library/src-bootstrapped/scala/quoted/Type.scala +++ b/library/src-bootstrapped/scala/quoted/Type.scala @@ -1,5 +1,6 @@ package scala.quoted +import scala.annotation.compileTimeOnly import scala.quoted.show.SyntaxHighlight /** Quoted type (or kind) `T` */ @@ -22,6 +23,10 @@ abstract class Type[X <: AnyKind] private[scala] { /** Some basic type tags, currently incomplete */ object Type { + /** Return a quoted.Type with the given type */ + @compileTimeOnly("Reference to `scala.quoted.Type.apply` was not handled by ReifyQuotes") + def apply[T <: AnyKind]: QuoteContext ?=> Type[T] = ??? + def UnitTag: QuoteContext ?=> Type[Unit] = qctx.tasty.defn.UnitType.seal.asInstanceOf[quoted.Type[Unit]] From cc00cbbc3fcf6e20b1528845d71bee09b24097c7 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 27 Jul 2020 18:03:08 +0200 Subject: [PATCH 4/8] Simplify synthetization of scala.quoted.Type --- .../dotty/tools/dotc/typer/Synthesizer.scala | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala index 1215df0a97a3..f1262cb6a160 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -48,23 +48,18 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): case _ => EmptyTree end synthesizedClassTag - /** Synthesize the tree for `'[T]` for an implicit `scala.quoted.Type[T]`. + /** Synthesize the tree for `scala.quoted.Type[T]` for an implicit `scala.quoted.Type[T]`. * `T` is deeply dealiased to avoid references to local type aliases. */ val synthesizedTypeTag: SpecialHandler = (formal, span) => - def quotedType(t: Type) = - val qctx = ctx.typer.inferImplicitArg(defn.QuoteContextClass.typeRef, span) - qctx.tpe match - case tpe: Implicits.SearchFailureType => report.error(tpe.msg, ctx.source.atSpan(span)) - case _ => - ref(defn.QuotedTypeModule_apply).appliedToType(t).select(nme.apply).appliedTo(qctx) - formal.argInfos match - case arg :: Nil => - val deepDealias = new TypeMap: - def apply(tp: Type): Type = mapOver(tp.dealias) - quotedType(deepDealias(arg)) + val qctx = ctx.typer.inferImplicitArg(defn.QuoteContextClass.typeRef, span) + qctx.tpe match + case tpe: Implicits.SearchFailureType => report.error(tpe.msg, ctx.source.atSpan(span)) case _ => - EmptyTree + val deepDealias = new TypeMap: + def apply(tp: Type): Type = mapOver(tp.dealias) + val t = deepDealias(formal.select(tpnme.spliceType)) + ref(defn.QuotedTypeModule_apply).appliedToType(t).select(nme.apply).appliedTo(qctx) end synthesizedTypeTag val synthesizedTupleFunction: SpecialHandler = (formal, span) => From 8fdadea4768868083607add3336d6aba1e39811e Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 27 Jul 2020 18:14:45 +0200 Subject: [PATCH 5/8] Update test output --- tests/run-staging/quote-nested-4.check | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-staging/quote-nested-4.check b/tests/run-staging/quote-nested-4.check index ebfd27eb5652..ca8eaa483f2f 100644 --- a/tests/run-staging/quote-nested-4.check +++ b/tests/run-staging/quote-nested-4.check @@ -1,5 +1,5 @@ ((qctx: scala.quoted.QuoteContext) ?=> { - val t: scala.quoted.Type[scala.Predef.String] = scala.internal.quoted.CompileTime.typeQuote[scala.Predef.String].apply(using qctx) + val t: scala.quoted.Type[scala.Predef.String] = scala.quoted.Type.apply[scala.Predef.String].apply(using qctx) (t: scala.quoted.Type[scala.Predef.String]) }) From 013b1e0146fb04ded51df11efaf4fb780ef9888b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 27 Jul 2020 18:41:43 +0200 Subject: [PATCH 6/8] Simplify printing of scala.quoted.Type.apply --- .../dotty/tools/dotc/printing/DecompilerPrinter.scala | 1 - .../src/dotty/tools/dotc/printing/RefinedPrinter.scala | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala b/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala index d5c75502ceee..261fd0aa637d 100644 --- a/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala @@ -75,6 +75,5 @@ class DecompilerPrinter(_ctx: Context) extends RefinedPrinter(_ctx) { override protected def typeApplyText[T >: Untyped](tree: TypeApply[T]): Text = if (tree.symbol eq defn.InternalQuoted_exprQuote) "'" - else if (tree.symbol eq defn.QuotedTypeModule_apply) "'[" ~ toTextGlobal(tree.args, ", ") ~ "]" else super.typeApplyText(tree) } diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index e36504b54cbc..ca4b217c5f35 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -267,13 +267,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { protected def typeApplyText[T >: Untyped](tree: TypeApply[T]): Text = { val isQuote = !printDebug && tree.fun.hasType && tree.fun.symbol == defn.QuotedTypeModule_apply - val (open, close) = if (isQuote) (keywordStr("'["), keywordStr("]")) else ("[", "]") - val funText = toTextLocal(tree.fun).provided(!isQuote) + val funText = toTextLocal(tree.fun) tree.fun match { case Select(New(tpt), nme.CONSTRUCTOR) if tpt.typeOpt.dealias.isInstanceOf[AppliedType] => funText // type was already printed by toText(new) case _ => - funText ~ open ~ toTextGlobal(tree.args, ", ") ~ close + funText ~ "[" ~ toTextGlobal(tree.args, ", ") ~ "]" } } @@ -632,9 +631,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { } case Number(digits, kind) => digits - case Quote(tree) => - if (tree.isType) keywordStr("'[") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("]") - else keywordStr("'{") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}") + case Quote(tree) if tree.isTerm => + keywordStr("'{") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}") case Splice(tree) => keywordStr("${") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}") case TypSplice(tree) => From 50691827b5274242db94d5a9315442772bd48963 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 28 Jul 2020 15:19:47 +0200 Subject: [PATCH 7/8] Simplify quoted.Type implicit search Now it is a plain `given` definition and follows the normal implicit resulution rules. Dealiasing of local inconsitent type aliases references are handled by `PCPCheckAndHeal` before healing is atempted. --- .../tools/dotc/transform/PCPCheckAndHeal.scala | 6 ++++-- .../src/dotty/tools/dotc/typer/Synthesizer.scala | 15 --------------- library/src-bootstrapped/scala/quoted/Type.scala | 2 +- tests/run-macros/i7048/Lib_1.scala | 2 +- 4 files changed, 6 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index 688e48971b40..f9499c6b4715 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -175,8 +175,10 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( tp match case tp: TypeRef => tp.prefix match - case NoPrefix if level > levelOf(tp.symbol) => - tryHeal(tp.symbol, tp, pos) + case NoPrefix if level > levelOf(tp.symbol) && !tp.typeSymbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) => + val tp1 = tp.dealias + if tp1 != tp then apply(tp1) + else tryHeal(tp.symbol, tp, pos) case prefix: ThisType if !tp.symbol.isStatic && level > levelOf(prefix.cls) => tryHeal(tp.symbol, tp, pos) case prefix: TermRef if tp.symbol.isTypeSplice => diff --git a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala index f1262cb6a160..4f000eb33dec 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -48,20 +48,6 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): case _ => EmptyTree end synthesizedClassTag - /** Synthesize the tree for `scala.quoted.Type[T]` for an implicit `scala.quoted.Type[T]`. - * `T` is deeply dealiased to avoid references to local type aliases. - */ - val synthesizedTypeTag: SpecialHandler = (formal, span) => - val qctx = ctx.typer.inferImplicitArg(defn.QuoteContextClass.typeRef, span) - qctx.tpe match - case tpe: Implicits.SearchFailureType => report.error(tpe.msg, ctx.source.atSpan(span)) - case _ => - val deepDealias = new TypeMap: - def apply(tp: Type): Type = mapOver(tp.dealias) - val t = deepDealias(formal.select(tpnme.spliceType)) - ref(defn.QuotedTypeModule_apply).appliedToType(t).select(nme.apply).appliedTo(qctx) - end synthesizedTypeTag - val synthesizedTupleFunction: SpecialHandler = (formal, span) => formal match case AppliedType(_, funArgs @ fun :: tupled :: Nil) => @@ -391,7 +377,6 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): val specialHandlers = List( defn.ClassTagClass -> synthesizedClassTag, - defn.QuotedTypeClass -> synthesizedTypeTag, defn.EqlClass -> synthesizedEql, defn.TupledFunctionClass -> synthesizedTupleFunction, defn.ValueOfClass -> synthesizedValueOf, diff --git a/library/src-bootstrapped/scala/quoted/Type.scala b/library/src-bootstrapped/scala/quoted/Type.scala index 7b5b097954c8..7f9dacba7adf 100644 --- a/library/src-bootstrapped/scala/quoted/Type.scala +++ b/library/src-bootstrapped/scala/quoted/Type.scala @@ -25,7 +25,7 @@ object Type { /** Return a quoted.Type with the given type */ @compileTimeOnly("Reference to `scala.quoted.Type.apply` was not handled by ReifyQuotes") - def apply[T <: AnyKind]: QuoteContext ?=> Type[T] = ??? + given apply[T <: AnyKind] as (QuoteContext ?=> Type[T]) = ??? def UnitTag: QuoteContext ?=> Type[Unit] = qctx.tasty.defn.UnitType.seal.asInstanceOf[quoted.Type[Unit]] diff --git a/tests/run-macros/i7048/Lib_1.scala b/tests/run-macros/i7048/Lib_1.scala index 2e38f9de1331..b2b0fc70f6c8 100644 --- a/tests/run-macros/i7048/Lib_1.scala +++ b/tests/run-macros/i7048/Lib_1.scala @@ -12,7 +12,7 @@ given [U] as IsExpr[Expr[U]] = new IsExpr[Expr[U]] { def f(x: Any): String = x.toString -def g[T](x: T)(using e: IsExpr[T], tu: Type[e.Underlying]): QuoteContext ?=> Expr[String] = { +def g[T](x: T)(using e: IsExpr[T])(using tu: Type[e.Underlying]): QuoteContext ?=> Expr[String] = { val underlying: Expr[e.Underlying] = e.toExpr(x) '{f($underlying)} } From 7c4fa0c6412677651fd319e892c4c3f633be1517 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 29 Jul 2020 09:40:37 +0200 Subject: [PATCH 8/8] Remove dead code --- compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index ca4b217c5f35..94c64a03e872 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -266,7 +266,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { ("{" ~ toText(trees, "\n") ~ "}").close protected def typeApplyText[T >: Untyped](tree: TypeApply[T]): Text = { - val isQuote = !printDebug && tree.fun.hasType && tree.fun.symbol == defn.QuotedTypeModule_apply val funText = toTextLocal(tree.fun) tree.fun match { case Select(New(tpt), nme.CONSTRUCTOR) if tpt.typeOpt.dealias.isInstanceOf[AppliedType] =>