diff --git a/compiler/src/dotty/tools/dotc/quoted/TreeCleaner.scala b/compiler/src/dotty/tools/dotc/quoted/TreeCleaner.scala index cb346ffa555e..6035d8900c6c 100644 --- a/compiler/src/dotty/tools/dotc/quoted/TreeCleaner.scala +++ b/compiler/src/dotty/tools/dotc/quoted/TreeCleaner.scala @@ -17,12 +17,14 @@ class TreeCleaner extends tpd.TreeMap { /** List of symbols and their types for type aliases `type T = U` */ private[this] var aliasesSyms: List[Symbol] = Nil private[this] var aliasesTypes: List[Type] = Nil + private[this] val aliases = newMutableSymbolMap[Tree] override def transform(tree: Tree)(implicit ctx: Context): Tree = { val tree0 = tree match { case TypeDef(_, TypeBoundsTree(lo, hi)) if lo == hi => aliasesSyms = tree.symbol :: aliasesSyms aliasesTypes = lo.tpe :: aliasesTypes + aliases(tree.symbol) = ref(lo.tpe.typeSymbol) Literal(Constant(())) case _ => tree } @@ -40,6 +42,7 @@ class TreeCleaner extends tpd.TreeMap { case expr3 => Block(flatStats, expr3) } case tree1: TypeTree => TypeTree(tree1.tpe.subst(aliasesSyms, aliasesTypes)) + case tree1: Ident => aliases.get(tree1.symbol).getOrElse(tree1) case tree1 => tree1 } } diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index ae6cb049ef4f..3005caa072cb 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -210,7 +210,10 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { explicitTags.clear() // Maps type splices to type references of tags e.g., ~t -> some type T$1 - val map: Map[Type, Type] = tagsExplicitTypeDefsPairs.map(x => (x._1, x._2.symbol.typeRef)).toMap + val map: Map[Type, Type] = { + tagsExplicitTypeDefsPairs.map(x => (x._1, x._2.symbol.typeRef)) ++ + (itags.map(_._1) zip typeDefs.map(_.symbol.typeRef)) + }.toMap val tMap = new TypeMap() { override def apply(tp: Type): Type = map.getOrElse(tp, mapOver(tp)) } @@ -245,7 +248,7 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { l == level || sym.is(Inline) && sym.owner.is(Macro) && sym.info.isValueType && l - 1 == level case None => - true + level == 0 } /** Issue a "splice outside quote" error unless we ar in the body of an inline method */ @@ -289,12 +292,12 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { if (!isThis) sym.show else if (sym.is(ModuleClass)) sym.sourceModule.show else i"${sym.name}.this" - if (!isThis && sym.maybeOwner.isType) + if (!isThis && sym.maybeOwner.isType && !sym.is(Param)) check(sym.owner, sym.owner.thisType, pos) else if (sym.exists && !sym.isStaticOwner && !levelOK(sym)) for (errMsg <- tryHeal(tp, pos)) ctx.error(em"""access to $symStr from wrong staging level: - | - the definition is at level ${levelOf(sym)}, + | - the definition is at level ${levelOf.getOrElse(sym, 0)}, | - but the access is at level $level.$errMsg""", pos) } @@ -313,7 +316,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { } case tp: NamedType => check(tp.symbol, tp, pos) - foldOver(acc, tp) + if (!tp.symbol.is(Param)) + foldOver(acc, tp) case tp: ThisType => check(tp.cls, tp, pos) foldOver(acc, tp) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 0c0c43dcc9aa..89ab240944f5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -571,7 +571,7 @@ trait Implicits { self: Typer => } def synthesizedTypeTag(formal: Type): Tree = formal.argInfos match { - case arg :: Nil => + case arg :: Nil if !arg.typeSymbol.is(Param) => object bindFreeVars extends TypeMap { var ok = true def apply(t: Type) = t match { diff --git a/tests/neg/i4350.scala b/tests/neg/i4350.scala new file mode 100644 index 000000000000..968a293424b2 --- /dev/null +++ b/tests/neg/i4350.scala @@ -0,0 +1,5 @@ +import scala.quoted.Type + +class Foo[T] { + '(null.asInstanceOf[T]) // error +} diff --git a/tests/pos/i4350.scala b/tests/pos/i4350.scala new file mode 100644 index 000000000000..7c6a82145cc9 --- /dev/null +++ b/tests/pos/i4350.scala @@ -0,0 +1,5 @@ +import scala.quoted.Type + +class Foo[T: Type] { + '(null.asInstanceOf[T]) +} diff --git a/tests/run-with-compiler/i4350.check b/tests/run-with-compiler/i4350.check new file mode 100644 index 000000000000..235eefbcd950 --- /dev/null +++ b/tests/run-with-compiler/i4350.check @@ -0,0 +1,6 @@ +{ + null.asInstanceOf[Object] +} +{ + null.asInstanceOf[String] +} diff --git a/tests/run-with-compiler/i4350.scala b/tests/run-with-compiler/i4350.scala new file mode 100644 index 000000000000..9657144f609d --- /dev/null +++ b/tests/run-with-compiler/i4350.scala @@ -0,0 +1,14 @@ +import dotty.tools.dotc.quoted.Toolbox._ + +import scala.quoted.Type + +class Foo[T: Type] { + def q = '(null.asInstanceOf[T]) +} + +object Test { + def main(args: Array[String]): Unit = { + println((new Foo[Object]).q.show) + println((new Foo[String]).q.show) + } +}