Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Cross-quotation references (CQR) allow one to write (this works with the changes in this PR):
(notice the call to
foo
at code-generation time, passing it a piece of code that contains an identifier bound in the outer quote)instead of having to either:
OpenCode
types, as it is unsound otherwise):All of these workarounds are quite unwieldy, and the lack of CQR has always been a pain.
CQR is hard to do because of the limited control given to macros, and the order in which macros expand. One of the sticking points has been to make the feature scope-safe, which means that we need to track that the inner quote refers to the outer quote's binding, so it cannot be extruded.
The approach taken here is to use
x.type
as the phantom context requirement associated with a cross-stage reference to thex
binding. The approach only works in quasi-code. I'm pretty sure it cannot be done with quasi-quotes without some sort of annotations (which defeats the purpose; at this point just use variable symbols), due to fundamental type checking and type inference reasons.This way, one can even mention the context requirements explicitly:
Note that in current Scala, writing the type explicitly only works if
x
extendsAnyRef
(otherwise Scala doesn't let you writex.type
), a dumb limitations that is apparently gone from Scala 2.13, fortunately. To work around this problem, I wrote asingleton.scope
macro insquid.utils.typing
, so that one can always writesingleton.scope.x
to meanx.type
, even forAnyVal
types.