Skip to content

Commit f691a18

Browse files
Merge pull request #6342 from dotty-staging/fix-#6263
Fix #6263: Register needsStaging when creating a synthetic quoted type
2 parents 2a033aa + a35d1bc commit f691a18

File tree

6 files changed

+75
-53
lines changed

6 files changed

+75
-53
lines changed

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,13 @@ class ReifyQuotes extends MacroTransform {
182182
capturers(body.symbol)(body)
183183
case _=>
184184
val (body1, splices) = nested(isQuote = true).splitQuote(body)(quoteContext)
185-
if (level == 0 && !ctx.inInlineMethod) {
185+
if (level == 0) {
186186
val body2 =
187187
if (body1.isType) body1
188188
else Inlined(Inliner.inlineCallTrace(ctx.owner, quote.sourcePos), Nil, body1)
189189
pickledQuote(body2, splices, body.tpe, isType).withSpan(quote.span)
190190
}
191191
else {
192-
// In top-level splice in an inline def. Keep the tree as it is, it will be transformed at inline site.
193192
body
194193
}
195194
}

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -217,29 +217,6 @@ object Applications {
217217
class ExtMethodApply(app: Tree)(implicit @constructorOnly src: SourceFile)
218218
extends IntegratedTypeArgs(app)
219219

220-
/** 1. If we are in an inline method but not in a nested quote, mark the inline method
221-
* as a macro.
222-
*
223-
* 2. If selection is a quote or splice node, record that fact in the current compilation unit.
224-
*/
225-
def handleMeta(tree: Tree)(implicit ctx: Context): tree.type = {
226-
import transform.SymUtils._
227-
228-
def markAsMacro(c: Context): Unit =
229-
if (c.owner eq c.outer.owner) markAsMacro(c.outer)
230-
else if (c.owner.isInlineMethod) c.owner.setFlag(Macro)
231-
else if (!c.outer.owner.is(Package)) markAsMacro(c.outer)
232-
val sym = tree.symbol
233-
if (sym.isSplice) {
234-
if (StagingContext.level == 0)
235-
markAsMacro(ctx)
236-
ctx.compilationUnit.needsStaging = true
237-
} else if (sym.isQuote) {
238-
ctx.compilationUnit.needsStaging = true
239-
}
240-
241-
tree
242-
}
243220
}
244221

245222
trait Applications extends Compatibility { self: Typer with Dynamic =>
@@ -820,7 +797,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
820797
* or, if application is an operator assignment, also an `Assign` or
821798
* Block node.
822799
*/
823-
def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = handleMeta {
800+
def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
824801

825802
def realApply(implicit ctx: Context): Tree = track("realApply") {
826803
val originalProto = new FunProto(tree.args, IgnoredProto(pt))(this, tree.isContextual)(argCtx(tree))
@@ -964,7 +941,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
964941
val isNamed = hasNamedArg(tree.args)
965942
val typedArgs = if (isNamed) typedNamedArgs(tree.args) else tree.args.mapconserve(typedType(_))
966943
record("typedTypeApply")
967-
handleMeta(typedFunPart(tree.fun, PolyProto(typedArgs, pt)) match {
944+
typedFunPart(tree.fun, PolyProto(typedArgs, pt)) match {
968945
case IntegratedTypeArgs(app) =>
969946
app
970947
case _: TypeApply if !ctx.isAfterTyper =>
@@ -986,7 +963,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
986963
}
987964
if (typedFn.tpe eq TryDynamicCallType) tryDynamicTypeApply()
988965
else assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs)
989-
})
966+
}
990967
}
991968

992969
/** Rewrite `new Array[T](....)` if T is an unbounded generic to calls to newGenericArray.

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -667,29 +667,36 @@ trait Implicits { self: Typer =>
667667
EmptyTree
668668
}
669669

670-
def synthesizedTypeTag(formal: Type): Tree = formal.argInfos match {
671-
case arg :: Nil if !arg.typeSymbol.is(Param) =>
672-
object bindFreeVars extends TypeMap {
673-
var ok = true
674-
def apply(t: Type) = t match {
675-
case t @ TypeRef(NoPrefix, _) =>
676-
inferImplicit(defn.QuotedTypeType.appliedTo(t), EmptyTree, span) match {
677-
case SearchSuccess(tag, _, _) if tag.tpe.isStable =>
678-
tag.tpe.select(defn.QuotedType_splice)
679-
case _ =>
680-
ok = false
681-
t
682-
}
683-
case _ => t
670+
def synthesizedTypeTag(formal: Type): Tree = {
671+
def quotedType(t: Type) = {
672+
if (StagingContext.level == 0)
673+
ctx.compilationUnit.needsStaging = true // We will need to run ReifyQuotes
674+
ref(defn.InternalQuoted_typeQuote).appliedToType(t)
675+
}
676+
formal.argInfos match {
677+
case arg :: Nil if !arg.typeSymbol.is(Param) =>
678+
object bindFreeVars extends TypeMap {
679+
var ok = true
680+
def apply(t: Type) = t match {
681+
case t @ TypeRef(NoPrefix, _) =>
682+
inferImplicit(defn.QuotedTypeType.appliedTo(t), EmptyTree, span) match {
683+
case SearchSuccess(tag, _, _) if tag.tpe.isStable =>
684+
tag.tpe.select(defn.QuotedType_splice)
685+
case _ =>
686+
ok = false
687+
t
688+
}
689+
case _ => t
690+
}
684691
}
685-
}
686-
val tag = bindFreeVars(arg)
687-
if (bindFreeVars.ok) ref(defn.InternalQuoted_typeQuote).appliedToType(tag)
688-
else EmptyTree
689-
case arg :: Nil if ctx.inInlineMethod =>
690-
ref(defn.InternalQuoted_typeQuote).appliedToType(arg)
691-
case _ =>
692-
EmptyTree
692+
val tag = bindFreeVars(arg)
693+
if (bindFreeVars.ok) quotedType(tag)
694+
else EmptyTree
695+
case arg :: Nil if ctx.inInlineMethod =>
696+
quotedType(arg)
697+
case _ =>
698+
EmptyTree
699+
}
693700
}
694701

695702
def synthesizedTastyContext(formal: Type): Tree =

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,7 @@ class Typer extends Namer
449449
}
450450
case qual =>
451451
if (tree.name.isTypeName) checkStable(qual.tpe, qual.sourcePos)
452-
val select = Applications.handleMeta(
453-
checkValue(assignType(cpy.Select(tree)(qual, tree.name), qual), pt))
452+
val select = checkValue(assignType(cpy.Select(tree)(qual, tree.name), qual), pt)
454453
if (select.tpe ne TryDynamicCallType) ConstFold(checkStableIdentPattern(select, pt))
455454
else if (pt.isInstanceOf[FunOrPolyProto] || pt == AssignProto) select
456455
else typedDynamicSelect(tree, Nil, pt)
@@ -1936,8 +1935,10 @@ class Typer extends Namer
19361935
ctx.warning("Canceled splice directly inside a quote. '{ ${ XYZ } } is equivalent to XYZ.", tree.sourcePos)
19371936
typed(innerExpr, pt)
19381937
case quoted if quoted.isType =>
1938+
ctx.compilationUnit.needsStaging = true
19391939
typedTypeApply(untpd.TypeApply(untpd.ref(defn.InternalQuoted_typeQuoteR), quoted :: Nil), pt)(quoteContext).withSpan(tree.span)
19401940
case quoted =>
1941+
ctx.compilationUnit.needsStaging = true
19411942
if (ctx.mode.is(Mode.Pattern) && level == 0) {
19421943
val exprPt = pt.baseType(defn.QuotedExprClass)
19431944
val quotedPt = if (exprPt.exists) exprPt.argTypesHi.head else defn.AnyType
@@ -2012,6 +2013,7 @@ class Typer extends Namer
20122013
ctx.warning("Canceled quote directly inside a splice. ${ '{ XYZ } } is equivalent to XYZ.", tree.sourcePos)
20132014
typed(innerExpr, pt)
20142015
case expr =>
2016+
ctx.compilationUnit.needsStaging = true
20152017
if (ctx.mode.is(Mode.QuotedPattern) && level == 1) {
20162018
if (isFullyDefined(pt, ForceDegree.all)) {
20172019
def spliceOwner(ctx: Context): Symbol =
@@ -2024,13 +2026,23 @@ class Typer extends Namer
20242026
tree.withType(UnspecifiedErrorType)
20252027
}
20262028
}
2027-
else
2029+
else {
2030+
if (StagingContext.level == 0) {
2031+
// Mark the first inline method from the context as a macro
2032+
def markAsMacro(c: Context): Unit =
2033+
if (c.owner eq c.outer.owner) markAsMacro(c.outer)
2034+
else if (c.owner.isInlineMethod) c.owner.setFlag(Macro)
2035+
else if (!c.outer.owner.is(Package)) markAsMacro(c.outer)
2036+
markAsMacro(ctx)
2037+
}
20282038
typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprSpliceR), tree.expr), pt)(spliceContext).withSpan(tree.span)
2039+
}
20292040
}
20302041
}
20312042

20322043
/** Translate ${ t: Type[T] }` into type `t.splice` while tracking the quotation level in the context */
20332044
def typedTypSplice(tree: untpd.TypSplice, pt: Type)(implicit ctx: Context): Tree = track("typedTypSplice") {
2045+
ctx.compilationUnit.needsStaging = true
20342046
checkSpliceOutsideQuote(tree)
20352047
typedSelect(untpd.Select(tree.expr, tpnme.splice), pt)(spliceContext).withSpan(tree.span)
20362048
}

compiler/test-resources/repl/i6263

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
scala> import quoted._
2+
scala> def fn[T : Type](v : T) = println("ok")
3+
def fn[T](v: T)(implicit evidence$1: quoted.Type[T]): Unit
4+
scala> fn("foo")
5+
ok
6+
scala> fn((1,2))
7+
ok
8+
scala> object O
9+
// defined object O
10+
scala> fn(O)
11+
ok
12+
scala> fn(1)
13+
ok

tests/run-with-compiler/i6263.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import quoted._
2+
object Test {
3+
4+
def main(args: Array[String]): Unit = {
5+
fn("foo")
6+
fn((1,2))
7+
fn(O)
8+
fn(1)
9+
}
10+
11+
def fn[T : Type](v : T) = "ok"
12+
}
13+
14+
object O

0 commit comments

Comments
 (0)