Can I disable the bitwise-negation operator for a crate?

My team just discovered (via a typo) that the rust ! operator performs a bitwise-negation for integer inputs. This is rarely what we're looking for, and so what we're really like is a way to either disable bitwise-negation completely for our crate, or maybe have a clippy or similar lint to warn/error on this.

In the case we actually did want bitwise negation, we could explicitly write out .not() using the std::ops::Not trait.

Does anyone know if this is possible? I looked through the clippy lints but didn't see this as an option.

This is sort of like the clippy::arithmetic restriction, but unfortunately that doesn't count bitwise negation (presumably since its main purpose is to avoid panics, and bitwise negation can't panic) so it can't be configured into doing what you want.

You can't disable parts of the syntax. A denied Clippy lint would be more appropriate, but I don't think this specific lint exists. You can write your own custom lint, though. It's not too hard.

Clippy's README says "please file an issue if you have ideas" for new lints. I suggest doing so, although indeed writing the lint yourselves presumably would allow you to use it sooner.

4 Likes

Can someone explain to me what "bitwise negation means?

A single bit is a zero or a one. There is no sign there. I can see an inversion, zero to one or vice versa, but not a negation.

Am I missing a point here?

"negation" is the term for flipping a boolean in Boolean Algebra

1 Like

Is it? Since when did that become accepted parlance? Back in the day flipping bits from 0 to 1, false to true, whatever you call, it was known as "inversion" or "NOT". As in NAND, NOR.

There is no way to negate a single bit.

Boolean Algebra is a field of mathematics. It doesn't have any concept of "bits", only variables and values which can be either true or false.

Negation in logic is established parlance for the logical complement operation. Whereas what the unary minus operator does is more commonly called the additive inverse in mathematics.

Indeed. As taught to us in school aged 13 or so back in the day.

A Boolean variable and a "bit" are the same thing as far as I can tell. TRUE or FALSE, HIGH or LOW, 0 or 1. The essence of the idea is that it is the minimum unit of information. Which we can of course represent in many ways.

Anyway, I have never seen a negation in Boolean Algebra. There is a "not" operator but that is not a negation.

OK. I give in. Somewhere along the line "negate" became synonymous with "not" whilst I was not looking :slight_smile:

It has been that way at least since 1602:

  • Troilus She was not, sure.
  • Ulysses Most sure she was.
  • Troilus Why, my negation hath no taste of madness.
8 Likes

Thank you all for your thoughts about terminology and boolean algebra. It seems that the answer is that this there doesn't exist a clippy lint for this already. I will consider submitting this as a proposed lint (and maybe a PR).

6 Likes

Brilliant retort.

However there was no Boolean logic in 1602. That formalisation came in 1854: The Laws of Thought - Wikipedia

Strangely there is no mention of negation in there.

Thanks for being patient with a mostly derailed thread.

7 Likes

One way to "disable" the !-operator is to newtype all your domain-specific types. Don't use the builtin types (especially the numeric ones) directly, and don't implement std::ops::Deref for the newtypes either.

That will prevent any kind of operator usage on such types that aren't explicitly implemented, and it's stronger than a lint since the code won't compile with undesirable operators mixed in.

3 Likes

Can you say more about the context in which you hit this and it wasn't a compilation error? Critically, the easy "I came from C" mistake of writing if !x to check if x != 0 doesn't compile in Rust, thanks to Rust not having truthiness.

(That's why Rust doesn't need the !-vs-~ distinction that's common in other languages.)

4 Likes