From d8e778d7b59c89e677ab967916b45e27cce07f75 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 8 Aug 2019 16:00:22 +0200 Subject: [PATCH 1/4] Fix #7013: Check PCP for all class references --- .../dotc/transform/PCPCheckAndHeal.scala | 33 +++++++++++-------- tests/neg/i7013.scala | 6 ++++ 2 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 tests/neg/i7013.scala diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index 5f1c769ccb6a..b738d5077e67 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -140,6 +140,8 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( if (sym.exists && !sym.isStaticOwner && !isClassRef && !levelOK(sym)) tryHeal(sym, tp, pos) + else if (sym.exists && !sym.owner.isStaticOwner && !levelOK(sym)) // local class reference that is phase + levelError(sym, tp, pos, "") else None } @@ -170,17 +172,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 +184,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 +} From faf948fc514c9c6e5920017af9249409efabd598 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 8 Aug 2019 16:13:08 +0200 Subject: [PATCH 2/4] Refactor coditions --- .../src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index b738d5077e67..3cb3b7e79e58 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -138,9 +138,11 @@ 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.exists && !sym.owner.isStaticOwner && !levelOK(sym)) // local class reference that is phase + else if (!sym.owner.isStaticOwner) // local class reference that is phase levelError(sym, tp, pos, "") else None From c823a12d93dae80bf47160e98832d6284238d2ac Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sat, 10 Aug 2019 16:47:08 +0200 Subject: [PATCH 3/4] Add tests --- tests/neg/i7013b.scala | 8 ++++++++ tests/neg/i7013c.scala | 6 ++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/neg/i7013b.scala create mode 100644 tests/neg/i7013c.scala 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 +} From e58a1604b695ed62f9018fb34b3c3fc8da07abea Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sat, 10 Aug 2019 19:04:53 +0200 Subject: [PATCH 4/4] Update comment --- compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index 3cb3b7e79e58..90c68d8e5b75 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -142,7 +142,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( None else if (!sym.isStaticOwner && !isClassRef) tryHeal(sym, tp, pos) - else if (!sym.owner.isStaticOwner) // local class reference that is phase + else if (!sym.owner.isStaticOwner) // non-top level class reference that is phase inconsistent levelError(sym, tp, pos, "") else None