-
Notifications
You must be signed in to change notification settings - Fork 1.7k
optimize booleans #790
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
optimize booleans #790
Conversation
One thing we could do to make this really applicable is to only lint when we manage to eliminate a term ( |
Nope, just checked, strings literal compare correctly. Most likely I’ll look at the rest later. |
This is bad, |
yea :( As I noted, these algorithms cut everything down to 2 levels of bool-ops. That's why I suggested
The number of uses of either
ah, yea, we should treat macro calls yielding bools as terminals... i'll add a bugfix |
no more hits in cargo and racer I split the lint into I also made sure that |
|
||
struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>); | ||
|
||
use quine_mc_cluskey::Bool; |
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.
Why is that use
here?
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.
to annoy enough so someone writes a lint warning about use
s in odd places?
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.
Seems legit 😄
That would be nice 😄
I would say that’s more optimized, but it’s surely clea{n,r}er. Except if
I’m not sure what you mean here.
Yes, that’s probably important. When I made the lints about copy&paste errors, I was told that servo (IIRC) had an instance of
|
Yeah, once any of the sub-expressions calls a method or macro, all bets are off – we should at least be wary to reorder code then, because Rust doesn't save us from side effects ( |
methods like
well since I'm using the an example would be |
could we somehow abuse marker traits to detect |
This is probably uncommon enough not to bother. |
done
yea, currently the optimized form might end up suggesting |
|
done. I don't think there are any more open questions. |
This is a great addition to our bag of tricks 😄 |
TLDR:
a || (a && b)
=>a
,!!a
=>a
,(a == b) && !(a == b)
=>false
, but still some quirks, feedback requestedcc #590
So... I implemented the Quine–McCluskey algorithm and Petrick's Method which together allow an algorithmic minimization of arbitrary boolean expressions (with fewer than 32 terminals). The full algorithm runs twice. Once for getting the smallest "sum of products" (
a && b && c || d && e || f
) and once for getting the smallest "product of sums" ((a || b || c) && (d || e) && f
). Then I check the list of smallest representations against the actual boolean expression. If the actual expression is the same (or some permutation of) one of the best ones, then I continue. Otherwise I dump all the better expressions as suggestions.This is not perfect yet. The algorithms assume mathematical boolean expressions. So they don't know about short circuiting,
xor
or comparison operations. Also every boolean expression with more than 2 levels gets flattened to 2 levels. I plan on tackling those issues in future improvements. I made the lint allow-by-default because of this.Open Questions:
a == b
anda != b
in the same boolean expression and use them (during optimization) asa == b
and!(a == b)
. This has some advantages (see below)!(a == b)
in the optimized expression intoa != b
or should this be a separate lint?Should stdlib comparison functions with inverses be treated like the builtin comparisons functions for the two previos points?UncommonShould I keep ignoring short circuiting behavior? Are there any situations where an optimized form of an expression would break?allow by default, except for logic bugschangingUncommon(!a && b) || (a && !b)
toa ^ b
is fine? there's no short circuiting possible anyway, separate lint?unwrappingUncommona ^ b
to the expanded form for optimization might yield better results in a larger expression, should this be done?and
and bitwiseor
100% equal to the regular boolean ops? This basically assumes that anyone using the non-fast-forwarding versions doesn't know what they are doing.some benchmarking on cargo with clippy compiled in release mode says it has (nearly?) no impact:
with
nonminimal_bool
:just clippy:
no clippy:
How annoying is this lint?
cargo:
suggested to change to
or
The previous expression was fine imo, but had 3 levels of and/or operations
One bug, must be in
SpanlessEq::expr_eq
:on racer:
suggests
and