-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Disallow phase inconsistent inline parameters #8061
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disallow phase inconsistent inline parameters #8061
Conversation
2ecdf91
to
b937f9f
Compare
334930e
to
07f104e
Compare
Will need to be rebased on #8077 (the second commit will disapear) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise, LGTM
inline def power(x: Double, inline n: Int) = ${ powerCode('x, 'n) } | ||
|
||
private def powerCode(x: Expr[Double], n: Expr[Int]): Expr[Double] = | ||
powerCode(x, n.value) // Transform `n` into an Int or emit an error if it is not possible |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe do it safely by n.getValue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has the same semantics as before. If the inline parameter is not a constant, an error is emitted.
def unapply[T](expr: Expr[T])(given valueOf: ValueOfExpr[T], qxtc: QuoteContext): Option[T] = | ||
valueOf(expr) | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have extractor for Const, a duplicate? The name Value
is a little misleading, if we in fact only want to get the literal const out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, Value is more general. I plan to replace and remove Const in another PR
* Otherwise returns the value. | ||
*/ | ||
final def value[U >: T](given qctx: QuoteContext, valueOf: ValueOfExpr[U]): U = | ||
valueOf(this).getOrElse(qctx.throwError(s"Expected a known value. \n\nThe value of: $show\ncould not be recovered using $valueOf", this)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems this method only invites errors in meta-programming, maybe we should just remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without it we would end up writing expr.getValue.get
all over the place which would crash the macro expansion. This alternative emits an error saying that the call expected a constant value. Pointing to the argument that is not a value.
@@ -18,6 +18,14 @@ class Expr[+T] private[scala] { | |||
*/ | |||
final def getValue[U >: T](given qctx: QuoteContext, valueOf: ValueOfExpr[U]): Option[U] = valueOf(this) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find getValue
is a little misleading, if what it does is to get the literal out. Maybe getLiteralValue
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not necessarily a literal value.
4e68df9
to
e90f44d
Compare
e90f44d
to
e56574f
Compare
In preparation for #8060.
Originally we used
inline
parameters as the way to recover statically known values from the arguments. This worked on some predefined types such as literal primitives, case objects, case classes, enums among others. The latter ones where ad-hoc addons without a clear specification.ValueOfExpr
also recovers statically known values but it is more general. It can be implemented for any arbitrary type that represents a value. In this PR we introduce some extra ways to use this such asExpr.value
,matching.Value
andmatching.ValueSeq
.ValueOfExpr
makes the current use of inline parameters completely redundant hence this PR replaces all uses of inline parameters by equivalent code usingValueOfExpr
.It also simplifies the PCP as it removes a special case from the rules.