Announcing Overflower

综合编程 2016-06-25

24 June 2016

Integer overflow handling is a problem in many languages. Some, like Java, don’t even have specialized methods to check or cope with overflow, so you’re left on your own. As I work with statistic computations that sometimes need higher precision than IEE754
double-width can give us, so using 64 bit integers is an appealing solution (that unlike bignums doesn’t kill performance). However, integers usually wrap around on overflow, which is a bad thing to happen if you try to optimize a value.

In Rust, the story is much better, with a compiler option to enable/disable overflow checks globally (and the default to enable them in debug builds, but disable them in release builds), checked/wrapping and saturating methods on all integral types and even wrapper types that use the specialized methods in arithmetic operations. However, I felt that this puzzle was missing a piece. Ideally, I’d want to just tell the compiler: “Within this method/module/crate, use wrapping operations” or something like that. Cheap to put in, cheap to delete again, and neither wrapper types nor long method calls instead of arithmetic operators.

As I recently gained some confidence inwriting procedural macros, I thought “how hard could this be”? So I set out to build a crate to do exactly this. As a cute pun, I named it “ overflower
”.

Use Cases

Apart from my rather specific use case (I want release all the way, and get checked overflow every now and then, but only in certain modules or even methods, to be easily switched in and out), there are other uses for such a crate. For example, specifying #[overflow(wrap)]
will ensure that arithmetic operations won’t cause inadvertent panics even in debugging mode, which appears to be quite valuable in panic handlers (because double-panics suck) or interrupt handlers (where you may not panic at all).

Also it lends itself to experiments like “what if that code used saturating arithmetic?”, which are a fun way to spend the time, for some damittedly rather improbable definition of fun. 🙂

Implementation

The first thing to note is that Rust uses traits to define arithmetic operators. Combine this with type inference, and you’ll get a number of problems if you try to replace e.g. x + y
with x.add_or_panic(y)
. Even without implementing std::ops::Add
for your own types, what if x
is a String
and y
is a &str
? Your code no longer compiles, that’s what!

Doing type inference on an AST is certainly possible, but I did not want to go that route, because it’s complex, cumbersome, error-prone and subject to change with future additions to Rust’s type system (for example, I hear impl trait
is going to be implemented before the end of the year). My time’s better invested in writing code or blog copy than trying to follow rustc’s type system.

As luck has it, just recently support for specialization landed in nightly. Since a procedural macro is a compiler plugin and thus has to use nightly anyway, why not use it to specialize our own traits for integer types and delegate to the std::ops
traits for everyone else? A quick proof-of-concept turned out to work, so I quickly implemented the beginnings of overflower_support
. This crate contains the traits that get called instead of those in std::ops
, and are specialized for integral types to handle overflow in a specific way.

Now all overflower has to do is to fold the code and replace binary operations with the corresponding method calls (actually the current version uses calls, which thanks to unified function call syntax works beautifully, and those don’t require the traits to be in scope). I also had toexpand macros so I could deal with overflow within macro expansions (I hear that this is going to change in the future, so procedural macros can work on pre-expanded code directly).

I note that the same technique could be used to dramatically simplifymutation testing.

Conclusion

I’m quite happy with the current state of overflower. There are some things to be done, notably I’ll need a lot more tests (and I’d be glad to merge your contributions!), but all in all, I feel this piece fits the overflow handling puzzle quite well. It’s a pity that I cannot use this in Java.

Or stable Rust for that matter. If the standard library could at least make the traits of the overflower_support
crate available, rewriting the plugin to use syntex would enable using this from within stable, but I’m not a core dev and don’t know whether they’d like the idea. This state of affairs is temporary anyway, because sooner or later specialization will land in stable and then we will, too.

So do you think this belongs in core? Discuss on rust-users
or /r/rust
.

Llogiq on stuff

责编内容by:Llogiq on stuff (源链)。感谢您的支持!

您可能感兴趣的

Functor Functors Posted on December 15, 2017 You can teach a new dog old tricks. One of the fun things about category theory is that once you’ve learned an idea i...
Messy Event Flows: Part 2 – What it should b... So,last time we looked at our event flow, and I went into detail about the problems we've had with it. The next step was to remodel our event flow, n...
Coding Review 2016 如白驹过隙,洋葱猴号 2016 次时光列车即将抵达下一站,过去这一年,我们共同亲历了里约奥运会上的精彩瞬间,到战区难民引发的全球关注;从英国脱欧到美国大选;从风靡全球的《Pokémon Go》到同样传遍朋友圈的《PPAP》... 2016 年有太多事件值得回忆,现在,让我们进行一次 C...
Programming “Mentors” There are a lot of mentors in the programming universe, and they all seem to do different things. Mentors from Codementors, for example, answer compl...
New Course: Getting to Know the Foundation XY Grid Have you mastered the new features of Foundation 6.4, such as its new grid system called the XY grid? If not, don't worry—our new course, Getting to ...