-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
ast/parser: Detect function rule head + contains keyword. #5526
ast/parser: Detect function rule head + contains keyword. #5526
Conversation
748314e
to
edef6d0
Compare
@@ -1734,6 +1734,24 @@ p { | |||
} | |||
} | |||
|
|||
func TestCompilerCheckSafetyFunctionAndContainsKeyword(t *testing.T) { |
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.
Originally, the check lived under check.go
, and so the compiler was doing the error checking. I left the extra test in, since it's not hurting anything, and it's nice to have a downstream safety check.
@@ -831,6 +831,10 @@ func (p *Parser) parseHead(defaultRule bool) (*Head, bool) { | |||
|
|||
switch p.s.tok { | |||
case tokens.Contains: // NOTE: no Value for `contains` heads, we return here | |||
// Catch error case of using 'contains' with a function definition rule head. |
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 is located before the scan to have the error location land on the keyword. Using p.save()
+ p.restore()
later would have a similar effect.
@@ -213,7 +213,6 @@ func (tc *typeChecker) checkRule(env *TypeEnv, as *AnnotationSet, rule *Rule) { | |||
var tpe types.Type | |||
|
|||
if len(rule.Head.Args) > 0 { |
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 is a minor diff that got left in after a local rebase (when the check moved from check.go
-> parser.go
).
We can't? I believe only But there might be more going on here, I just got surprised by the statement in isolation 🙃 |
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.
Thanks! Nitpicks only. 👍
ast/parser.go
Outdated
@@ -831,6 +831,10 @@ func (p *Parser) parseHead(defaultRule bool) (*Head, bool) { | |||
|
|||
switch p.s.tok { | |||
case tokens.Contains: // NOTE: no Value for `contains` heads, we return here | |||
// Catch error case of using 'contains' with a function definition rule head. | |||
if len(head.Args) > 0 { | |||
p.illegal("the contains keyword can only be used with partial set definitions (e.g., %s contains <VALUE> { ... })", name) |
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.
So we've tacitly tried to shift terminology from "partial object", "partial set" and "complete rule" to "multi-value rule" and "single-value rule", with the introduction of ref heads.
Rule head | before | after |
---|---|---|
p contains x | partial set | multi-value rule |
p[x] = y | partial object | single-value rule |
p = y | complete rule | single-value rule |
This looks like another opportunity for using "multi-value rule".
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.
Thanks for the correction! I noticed the unfamiliar "multi-value rule" language in the error messages, but wasn't exactly sure how to interpret what I was seeing.
I've rolled the language shift into my latest changes.
5b6a6f6
to
376ddff
Compare
@srenatus You were right to be surprised! Because I was wrong, and the PR has wound up better for the correction. 😅 For some reason, I had gotten confused about the nil rules in Go, and that resulted in a less-accurate check. I've fixed the goofy logic, and added an extra test case to check for the "function with 0 arguments" case. |
Previously, we did not detect misuses of the `contains` keyword, which is only valid as a syntactic sugar for partial set definition rules. This commit adds some logic to detect when a function rule head has been paired with the `contains` keyword, which should generally be an error condition. Fixes: open-policy-agent#5525 Signed-off-by: Philip Conrad <[email protected]>
376ddff
to
841c0ee
Compare
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.
👏 🎉 Thanks!
Previously, we did not detect misuses of the
contains
keyword, which is only valid as a syntactic sugar for partial set definition rules.This PR adds some logic to detect when a function rule head has been paired with the
contains
keyword, which should generally be an error condition.Note: We can't catch the following case, because the number of args is zero, and we can't distinguishnil
from[]
in Go.EDIT: I was a smidge tired when I made the initial PR, and mixed up the nil rules in Golang around slices. It's
len()
that doesn't distinguish betweennil
and[]
. Silly mistakes happen, even to the best of us. 😅 (Thanks for the correction, @srenatus!)Fixes: #5525