diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index 5f1c769ccb6a..90c68d8e5b75 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -138,8 +138,12 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( /** Is a reference to a class but not `this.type` */ def isClassRef = sym.isClass && !tp.isInstanceOf[ThisType] - if (sym.exists && !sym.isStaticOwner && !isClassRef && !levelOK(sym)) + if (!sym.exists || levelOK(sym)) + None + else if (!sym.isStaticOwner && !isClassRef) tryHeal(sym, tp, pos) + else if (!sym.owner.isStaticOwner) // non-top level class reference that is phase inconsistent + levelError(sym, tp, pos, "") else None } @@ -170,17 +174,6 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( * to be added to the "inconsistent phase" message. */ protected def tryHeal(sym: Symbol, tp: Type, pos: SourcePosition)(implicit ctx: Context): Option[Tree] = { - def levelError(errMsg: String) = { - def symStr = - if (!tp.isInstanceOf[ThisType]) sym.show - else if (sym.is(ModuleClass)) sym.sourceModule.show - else i"${sym.name}.this" - ctx.error( - em"""access to $symStr from wrong staging level: - | - the definition is at level ${levelOf(sym).getOrElse(0)}, - | - but the access is at level $level.$errMsg""", pos) - None - } tp match { case tp: TypeRef => if (level == -1) { @@ -193,19 +186,33 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( case _: TermRef => Some(tag.select(tpnme.splice)) case _: SearchFailureType => - levelError(i""" + levelError(sym, tp, pos, + i""" | | The access would be accepted with the right type tag, but | ${ctx.typer.missingArgMsg(tag, reqType, "")}""") case _ => - levelError(i""" + levelError(sym, tp, pos, + i""" | | The access would be accepted with an implict $reqType""") } } case _ => - levelError("") + levelError(sym, tp, pos, "") } } + private def levelError(sym: Symbol, tp: Type, pos: SourcePosition, errMsg: String) given Context = { + def symStr = + if (!tp.isInstanceOf[ThisType]) sym.show + else if (sym.is(ModuleClass)) sym.sourceModule.show + else i"${sym.name}.this" + the[Context].error( + em"""access to $symStr from wrong staging level: + | - the definition is at level ${levelOf(sym).getOrElse(0)}, + | - but the access is at level $level.$errMsg""", pos) + None + } + } diff --git a/tests/neg/i7013.scala b/tests/neg/i7013.scala new file mode 100644 index 000000000000..95df35dded80 --- /dev/null +++ b/tests/neg/i7013.scala @@ -0,0 +1,6 @@ +import quoted._ + +def foo() given QuoteContext = { + class C + '[C] // error +} diff --git a/tests/neg/i7013b.scala b/tests/neg/i7013b.scala new file mode 100644 index 000000000000..092fb936a8a5 --- /dev/null +++ b/tests/neg/i7013b.scala @@ -0,0 +1,8 @@ +import quoted._ + +class Foo { + class Bar + def foo() given QuoteContext = { + '[Bar] // error + } +} diff --git a/tests/neg/i7013c.scala b/tests/neg/i7013c.scala new file mode 100644 index 000000000000..16a3ae1f5f84 --- /dev/null +++ b/tests/neg/i7013c.scala @@ -0,0 +1,6 @@ +import quoted._ + +def foo() given QuoteContext = { + type C + '[C] // error +}