Inhibit typer to insert contextual arguments when it is inside arguments of HOAS patterns #18040
+45
−10
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.
This will close #17905.
Current behavior and issue
Consider the following macro:
In theory, running this code should allow the quote '{ def f(using t: String)... } to match against the first clause of testCtxParamImpl, binding $a to '{ g => g + " outside"}. As such, we'd expect Test_2.scala to output (inside given) outside.
However, compiling Macro_1.scala results in the following error:
The issue stems from the method symbol
g
in the HOAS pattern$a(g)
. Here,g
should represent a symbol that can appear in the pattern variable$a
. It's not intended to mean a method call, yet the compiler treats it as such, attempts to insert explicit contextual arguments, and fails.Approach to fix this issue
It is
Typer.adaptNoArgs
that inserts explicit contextual arguments. I added the following condition!ctx.mode.is(Mode.InQuotePatternHoasArgs)
to prevent it from inserting contextual arguments.https://github.com/lampepfl/dotty/pull/18040/files#diff-8c9ece1772bd78160fc1c31e988664586c9df566a1d22ff99ef99dd6d5627a90R4064
Mode.InQuotePatternHoasArgs
is a new mode for typing arguments of a HOAS pattern. This solution works, as all existing tests have passed. However, considering that the number of Modes is limited to 32 in the current implementation, it might not be the most optimal approach.Discussion: Matching against contextual/implicit methods
An aspect to consider is how the quote pattern match should treat normal/contextual/implicit methods. For instance, consider this macro:
If we run
testMethods { given Int = 0; def f(implicit s: Int) = "placeholder"; f }
, how should it be handled?If pattern matching is done exactly, it should match the third pattern. However, given the similar behavior of using and implicit, it could reasonably match the second pattern. Alternatively, the pattern matcher can forget any information about context parameters, matching the first pattern -- which is the current behavior.
In the current implementation (even without this fix),
testMethods { given Int = 0; def f(implicit s: Any) = "placeholder"; f(10) }
expands to"matched normal method"
. This suggests that quote pattern matching disregards whether method parameters are contextual or not.This behavior has its merits; it removes the need to provide different patterns to match both normal and contextual methods. However, changing this behavior could disrupt macros dependent on the current behavior, potentially breaking the backward compatibility of quote pattern matching.
The question remains: should we maintain the current behavior, or alter the quote pattern matcher to differentiate between normal and contextual methods?