score:7

Accepted answer

It turns out that a very natural intent to generate a secondary constructor in a macro annotation has exposed two different issues.

1) The first issue (https://issues.scala-lang.org/browse/SI-8451) is about quasiquotes emitting wrong tree shapes for secondary constructors. That was fixed in 2.11.0-RC4 (yet to be released, currently available as 2.11.0-SNAPSHOT) and in paradise 2.0.0-M6 for 2.10.x (released yesterday).

2) The second issue is about unassigned positions wreaking havoc during typechecker. Curiously enough, when typechecking calls to constructors, typer uses positions in order to decide whether these calls are legal or not. That can't be patched that easily, and we have to work around:

         val newCtor = q"""def this() = this(List(Some("")))"""
-        val newBody = body :+ newCtor
+
+        // It looks like typer sometimes uses positions to decide whether stuff
+        // (secondary constructors in this case) typechecks or not (?!!):
+        // https://github.com/xeno-by/scala/blob/c74e1325ff1514b1042c959b0b268b3c6bf8d349/src/compiler/scala/tools/nsc/typechecker/Typers.scala#L2932
+        //
+        // In general, positions are important in getting error messages and debug
+        // information right, but maintaining positions is too hard, so macro writers typically don't care.
+        //
+        // This has never been a problem up until now, but here we're forced to work around
+        // by manually setting an artificial position for the secondary constructor to be greater
+        // than the position that the default constructor is going to get after macro expansion.
+        //
+        // We have a few ideas how to fix positions in a principled way in Palladium,
+        // but we'll have to see how it goes.
+        val defaultCtorPos = c.enclosingPosition
+        val newCtorPos = defaultCtorPos.withEnd(defaultCtorPos.endOrPoint + 1).withStart(defaultCtorPos.startOrPoint + 1).withPoint(defaultCtorPos.    point + 1)
+        val newBody = body :+ atPos(newCtorPos)(newCtor)

Related Query

More Query from same tag