Description
I'm writing a ScalaTest macro, where I find it helpful to have syntax for method types.
The use case is to transform the source code:
assert(5 === 6)
which is desugared as:
assert(
AssertionsSpec.this.convertToEqualizer[scala.Int](5).===(6)(scalactic.Equality.default[scala.Int])
)
and macro expanded to something like the follows:
{
val lhs = 5
val rhs = 6
val result = AssertionsSpec.this.convertToEqualizer[scala.Int](lhs).===(rhs)(scalactic.Equality.default[scala.Int])
val _bool = Bool.binaryMacroBool(lhs, "===", rhs, result)
Assertions.assertionsHelper.macroAssert(_bool, "", pos)
}
The natural thing to do in the implementation is to seal the following tree as a whole:
AssertionsSpec.this.convertToEqualizer[scala.Int]
The ideal implementation is something like the following:
val fun = fn.seal[(Any)Equalizer[_]]
val left = lhs.seal[Any]
val right = rhs.seal[Any]
val equality = eq.seal[Equality[_]]
'{
val _left = ~left
val _right = ~right
val _result = ~fun(_left).===(_right)(~equality)
val _bool = Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
Assertions.assertionsHelper.macroAssert(_bool, ~clue, ~pos)
}
Note that in the implemetation, we used the syntax for method type: (Any)Equalizer[_]
.
Or, we can provide tree constructors (Related #5438):
// How to do overloading resolution for `===`?
def result(l: Expr[Any], r: Expr[Any]) =
fn.appliedTo(l.unseal).select("===").appliedTo(r.unseal).appliedTo(eq.unseal).seal[Boolean]
val left = lhs.seal[Any]
val right = rhs.seal[Any]
'{
val _left = ~left
val _right = ~right
val _result = ~result(_left, _right)
val _bool = Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
Assertions.assertionsHelper.macroAssert(_bool, ~clue, ~pos)
}
However, the constructor-approach is inferior: in the quote-approach overloading resolution is a given for free, while in the constructor-approach it will be a burden on macro authors or the constructors have to do overloading resolution. AFAIK, the latter is not in the scope of #5438, @nicolasstucki mentioned adapation should be avoided in constructors.