Skip to content
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: generate new wildcards for else #5412

Conversation

srenatus
Copy link
Contributor

@srenatus srenatus commented Nov 22, 2022

The previous behaviour had triggered a check in the formatter for multiple use of wildcard variables:

 f(_) := true { true }
 else := false

The formatter found $1, the _ argument of f, again in else, and thus changed it into _1:

 f(_1) := true { true }
 else := false

There's no extra meaning to the copied wildcards in else, they should not count as second usage.

Fixes #5347.

⚠️ It does not fix the case where a rewriting is necessary, and clashes with an existing var. But it makes the rewriting a lot less likely; and notably doesn't do it just because there is an else defined for a function.

@srenatus srenatus marked this pull request as ready for review November 22, 2022 13:03
if v, ok := rule.Head.Args[i].Value.(Var); ok && v.IsWildcard() {
rule.Head.Args[i].Value = Var(p.genwildcard())
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The copy here had been misleading the "wildcard unmangling" logic in the formatter: https://github.com/open-policy-agent/opa/blob/main/format/format.go#L168

It picked up the else's invisible args and counted them as a second use that would necessitate the unmangling. It really doesn't, though, and is best sidestepped by introducing fresh wildcard variables for the else args in the first place.

@@ -4830,6 +4854,9 @@ func assertParseRule(t *testing.T, msg string, input string, correct *Rule, opts
if !rule.Head.Ref().Equal(correct.Head.Ref()) {
t.Errorf("Error on test \"%s\": rule heads not equal: ref = %v (parsed), ref = %v (correct)", msg, rule.Head.Ref(), correct.Head.Ref())
}
if !rule.Head.Equal(correct.Head) {
t.Errorf("Error on test \"%s\": rule heads not equal: %v (parsed), %v (correct)", msg, rule.Head, correct.Head)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just made the comparison a little more helpful. It's not much, but anyways.

Copy link
Contributor

@philipaconrad philipaconrad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 👍

The previous behaviour had triggered a check in the formatter for multiple
use of wildcard variables:

     f(_) := true { true }
     else := false

The formatter found `$1`, the `_` argument of f, again in else, and thus
changed it into `_1`:

     f(_1) := true { true }
     else := false

There's no extra meaning to the copied wildcards in `else`, they should not
count as second usage.

Signed-off-by: Stephan Renatus <[email protected]>
@philipaconrad philipaconrad force-pushed the sr/ast/no-wildcard-copies-for-else branch from cedd478 to 5a08964 Compare November 23, 2022 17:00
@philipaconrad philipaconrad merged commit 280cce6 into open-policy-agent:main Nov 23, 2022
@srenatus srenatus deleted the sr/ast/no-wildcard-copies-for-else branch November 23, 2022 18:38
srenatus added a commit to srenatus/opa that referenced this pull request Nov 29, 2022
This is a spiritual follow-up to open-policy-agent#5412.

A policy like

    f(_) := 1 { true } { true } { true }

would have been pretty-printed as

    f(_0) := 1
    f(_0) := 1
    f(_0) := 1

because of the duplicated wildcards.

They now get the same treatment as "else" gets: fresh wildcards.

Signed-off-by: Stephan Renatus <[email protected]>
srenatus added a commit that referenced this pull request Nov 29, 2022
This is a spiritual follow-up to #5412.

A policy like

    f(_) := 1 { true } { true } { true }

would have been pretty-printed as

    f(_0) := 1
    f(_0) := 1
    f(_0) := 1

because of the duplicated wildcards.

They now get the same treatment as "else" gets: fresh wildcards.

Signed-off-by: Stephan Renatus <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

fmt: _ in args getting rewritten to _0, _1...
2 participants