Skip to content

Commit

Permalink
additional diagnostics for overloading
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mie6 committed Apr 27, 2024
1 parent d1d0967 commit 60f1ef7
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 20 deletions.
31 changes: 19 additions & 12 deletions parsley-debug/shared/src/main/scala-2/parsley/debuggable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,8 @@ private object debuggable {
private def collect(c: blackbox.Context)(treeName: String, defs: List[c.Tree], recon: List[c.Tree] => c.Tree): c.Tree = {
import c.universe._
val parsleyTy = c.typeOf[Parsley[_]].typeSymbol
val noBody = atPos(c.enclosingPosition)(q"??? : @scala.annotation.nowarn")
lazy val noBody = atPos(c.enclosingPosition)(q"??? : @scala.annotation.nowarn")
// can't typecheck constructors in a stand-alone block
// FIXME: we need to patch overloads here: store the set of seen names, then a map from (name, pos) to freshName
// these will be used lookup the right name in the typemap later on
// the original function will be removed from the body and replaced
// this may break the typechecking for the rest of the object, which will need diagnostic checks for
// overloaded name use later
val seenNames = mutable.Set.empty[TermName]
val overloadMap = mutable.Map.empty[(TermName, Position), TermName]
val noConDefs = defs.flatMap {
Expand All @@ -79,7 +74,7 @@ private object debuggable {
overloadMap += ((name, dfn.pos) -> name)
name
}
Some(atPos(dfn.pos)(DefDef(mods, finalName, tyArgs, args, tpt, if (tpt.nonEmpty) noBody else body)))
Some(atPos(dfn.pos)(DefDef(mods, finalName, tyArgs, args, tpt, if (tpt.nonEmpty) q"???" else body)))
case dfn => Some(dfn)
}
val classlessBlock = q"..${noConDefs}"
Expand All @@ -100,7 +95,7 @@ private object debuggable {
// in this case, we are stuck
case _ =>
if (noConDefs.nonEmpty) {
val faultDetermined = doDiagnostics(c)(typelessDefs)
val faultDetermined = doDiagnostics(c)(overloadMap.keys.map(_._1).toSet, typelessDefs)
if (!faultDetermined) {
c.error(c.enclosingPosition, s"annotating `$treeName` failed because of a macro typechecking failure, with no identifiable diagnostic; please report to parsley maintainers")
}
Expand All @@ -125,10 +120,11 @@ private object debuggable {
recon(defs :+ registration)
}

private def doDiagnostics(c: blackbox.Context)(dfns: List[c.Tree]) = {
private def doDiagnostics(c: blackbox.Context)(overloadings: Set[c.TermName], dfns: List[c.Tree]) = {
var faultDetermined = false
for (dfn <- dfns) {
val problemFound = reportAnonClass(c)(dfn)
var problemFound = reportAnonClass(c)(dfn)
problemFound ||= reportOverloading(c)(overloadings, dfn)
faultDetermined ||= problemFound
if (problemFound) c.error(dfn.pos, s"this definition needs an explicit type annotation for the debugging annotation to work")
}
Expand All @@ -140,7 +136,6 @@ private object debuggable {
for (dfn <- dfns) {
val problemFoundDfn = reportUsedEnclosing(c)(enclosingName, dfn)
problemFound ||= problemFoundDfn
// FIXME: cannot handle overloading
if (problemFoundDfn) c.error(dfn.pos, s"this definition needs an explicit type annotation for the debugging annotation to work")
}
if (problemFound) {
Expand All @@ -155,11 +150,23 @@ private object debuggable {
case _ => false
}
for (anonClass <- anonClasses) {
c.echo(anonClass.pos, s"anonymous classes don't work properly with `parsley.debuggable`")
c.echo(anonClass.pos, "anonymous classes don't work properly with `parsley.debuggable`")
}
anonClasses.nonEmpty
}

private def reportOverloading(c: blackbox.Context)(overloadings: Set[c.TermName], dfn: c.Tree) = {
import c.universe._
val badOverloadings = dfn.filter {
case Ident(tn: TermName) => overloadings.contains(tn)
case _ => false
}
for (badOverloading <- badOverloadings) {
c.echo(badOverloading.pos, s"overloaded functions defined within annotated object can't be used reliably")
}
badOverloadings.nonEmpty
}

private def reportUsedEnclosing(c: blackbox.Context)(enclosingName: String, dfn: c.Tree) = {
import c.universe._
val badUse = dfn.find {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,25 @@ abstract class Tokens {
def tokens: List[Parsley[String]]
}

/*@experimental @parsley.debuggable
@experimental @parsley.debuggable
private object overloads {
def checkNo(symb: String, name: String, reasonGiven: String): Parsley[Nothing] = empty
def checkNo(symb: String, reason: String): Parsley[Nothing] = empty
}*/
def checkNo(symb: String, name: String, reasonGiven: String): Parsley[Nothing] = checkNo(symb, name, reasonGiven)
def checkNo(symb: String, reason: String): Parsley[Nothing] = checkNo(symb, reason)

lazy val p: Parsley[Int] = checkNo("", "", "")
lazy val q: Parsley[Int] = checkNo("", "")
}

/*@experimental @parsley.debuggable
@experimental @parsley.debuggable
private object anonClass {
class oops {
abstract class oops {
def foo(x: Int): Int
}

val p = new oops {
val p: oops = new oops {
def foo(x: Int) = x + 1
}

val anonClass = pure(6)
val x: Parsley[Char] = anonClass ~> char('a')
}*/
}

0 comments on commit 60f1ef7

Please sign in to comment.