diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index d7fa5ababa5f..03f604d2c5d8 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -9,6 +9,7 @@ import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.core.Flags._ import dotty.tools.dotc.core.quoted._ +import dotty.tools.dotc.core.Mode import dotty.tools.dotc.core.NameKinds._ import dotty.tools.dotc.core.StagingContext._ import dotty.tools.dotc.core.StdNames._ @@ -49,7 +50,10 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( case annot => transform(annot.tree)(given annotCtx) } checkLevel(super.transform(tree)) - case _ => checkLevel(super.transform(tree)) + case _ => + val ctx1 = if tree.isType then ctx.addMode(Mode.Type) else ctx + given Context = ctx1 + checkLevel(super.transform(tree)) } /** Transform quoted trees while maintaining phase correctness */ @@ -100,7 +104,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( case Some(tpRef) => tpRef case _ => tree } - case _: TypeTree | _: AppliedTypeTree | _: Apply | _: TypeApply | _: UnApply | Select(_, OuterSelectName(_, _)) => + case _: TypeTree | _: AppliedTypeTree | _: Apply | _: UnApply | Select(_, OuterSelectName(_, _)) => tree.withType(checkTp(tree.tpe)) case _: ValOrDefDef | _: Bind => tree.symbol.info = checkTp(tree.symbol.info) @@ -179,6 +183,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( case tp: TypeRef => if levelOf(sym).getOrElse(0) < level then tryHeal(sym, tp, pos) else None + case _: TermRef if ctx.mode.is(Mode.Type) && levelOf(sym).getOrElse(0) >= level => None case _ => levelError(sym, tp, pos, "") else if (!sym.owner.isStaticOwner) // non-top level class reference that is phase inconsistent diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index 0ed3e18429c8..242e33d2d747 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -231,8 +231,7 @@ class ReifyQuotes extends MacroTransform { if (isType) ref(defn.Unpickler_unpickleType).appliedToType(originalTp) else ref(defn.Unpickler_unpickleExpr).appliedToType(originalTp.widen) val spliceResType = - if (isType) defn.QuotedTypeClass.typeRef.appliedTo(WildcardType) - else defn.FunctionType(1, isContextual = true).appliedTo(defn.QuoteContextClass.typeRef, defn.QuotedExprClass.typeRef.appliedTo(defn.AnyType)) | defn.QuotedTypeClass.typeRef.appliedTo(WildcardType) + defn.FunctionType(1, isContextual = true).appliedTo(defn.QuoteContextClass.typeRef, defn.QuotedExprClass.typeRef.appliedTo(defn.AnyType)) | defn.QuotedTypeClass.typeRef.appliedTo(WildcardType) val pickledQuoteStrings = liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType) val splicesList = liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), spliceResType)) meth.appliedTo(pickledQuoteStrings, splicesList) diff --git a/library/src/scala/internal/quoted/Unpickler.scala b/library/src/scala/internal/quoted/Unpickler.scala index 2fab9bfc01be..f2555b9a1157 100644 --- a/library/src/scala/internal/quoted/Unpickler.scala +++ b/library/src/scala/internal/quoted/Unpickler.scala @@ -7,7 +7,7 @@ object Unpickler { type PickledQuote = List[String] type PickledExprArgs = Seq[Seq[Any] => ((QuoteContext ?=> Expr[Any]) | Type[_])] - type PickledTypeArgs = Seq[Seq[Any] => Type[_]] + type PickledTypeArgs = Seq[Seq[Any] => ((QuoteContext ?=> Expr[Any]) | Type[_])] /** Unpickle `repr` which represents a pickled `Expr` tree, * replacing splice nodes with `args` diff --git a/tests/neg/i8100.scala b/tests/neg/i8100.scala new file mode 100644 index 000000000000..3bf0bac845af --- /dev/null +++ b/tests/neg/i8100.scala @@ -0,0 +1,21 @@ + +import scala.quoted._ +import scala.quoted.matching._ + +class M { + type E +} + +def f[T: Type](using QuoteContext) = + summonExpr[M] match + case Some('{ $mm : $tt }) => + '{ + val m = $mm + ${ val b: m.type = + m // error + ??? + } + } + + +def g[T](using Type[T]) = ??? diff --git a/tests/pos/i8100.scala b/tests/pos/i8100.scala new file mode 100644 index 000000000000..fa2dcc3c054c --- /dev/null +++ b/tests/pos/i8100.scala @@ -0,0 +1,25 @@ + +import scala.quoted._ +import scala.quoted.matching._ + +class M { + type E +} + +def f(using QuoteContext): Expr[Any] = + val mm: Expr[M] = ??? + '{ + val m: M = $mm + type ME = m.E + ${ g[ME](using '[ME]) } + ${ g[m.E](using '[ME]) } + ${ g[ME](using '[m.E]) } + ${ g[m.E](using '[m.E]) } + // ${ g[ME] } // FIXME + // ${ g[m.E] } // FIXME + ${ g(using '[ME]) } + ${ g(using '[m.E]) } + } + + +def g[T](using Type[T]) = ???