<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, Jun 22, 2014 at 11:05 PM, Daniel Micay <span dir="ltr"><<a href="mailto:danielmicay@gmail.com" target="_blank">danielmicay@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="">On 22/06/14 09:31 AM, Gábor Lehel wrote:<br>
><br>
> The prospect of future architectures with cheaper (free) overflow<br>
> checking isn't my primary motivation, though if we also end up better<br>
> prepared for them as a side effect, that's icing on the cake.<br>
<br>
</div>It's never going to be free or even cheap. Replacing very common pure<br>
operations with impure ones in most code will destroy performance. Rust<br>
relies heavily on compiler optimizations to even come close to C level<br>
performance. Anyway, no one has offered an explanation of how they're<br>
planning on integrating this into LLVM and how they propose turning a<br>
trapping operation into unwinding across various platforms.<br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class=""><br>
> My primary motivation is that, outside of a couple of specialized cases<br>
> like hashing and checksums, wraparound semantics on overflow is<br>
> **wrong**. It may be well-defined behavior, and it may be fast, but it's<br>
> **wrong**. What's the value of a well-defined, performant semantics<br>
> which does the wrong thing?<br>
<br>
</div>Few functions check all of the necessary preconditions. For example, a<br>
binary search implementation doesn't check to see if the array is<br>
sorted.  It's not incorrect to require a precondition from the caller<br>
and overflow is only one of countless cases of this.<br></blockquote><div><br></div><div>Checking preconditions is a good thing. The fact that we can't have the good thing in some instances is not an argument for not having it in other instances.<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Choosing to enforce invariants in the type system or checking them at<br>
runtime is always a compromise, and Rust eschews runtime checks not<br>
strictly required for memory safety.<br>
<br>
In some cases, the type system has been leveraged to enforce invariants<br>
at compile-time (Ord vs. PartialOrd) but even though that's quite easy<br>
to sidestep, it's not without drawbacks.<br>
<div class=""><br>
> I also agree that performance is non-negotiable in this case, however.<br>
> The only good thing about always wrong is that it's not that hard to do<br>
> better.<br>
><br>
> Given the circumstances, I think the least bad outcome we could achieve,<br>
> and which we *should* aim to achieve, would be this:<br>
><br>
>  * Where performance is known to not be a requirement, Rust code in the<br>
> wild uses either overflow-checked arithmetic or unbounded integer types,<br>
> with the choice between them depending on ergonomic and semantic<br>
> considerations.<br>
><br>
>  * When the performance requirement can't be ruled out, Rust code in the<br>
> wild uses arithmetic for which overflow checking can be turned on or off<br>
> with a compiler flag. For testing and debugging, it is turned on. For<br>
> production and benchmarks, it is turned off.<br>
<br>
</div>The Rust developers have been consistently opposed to introducing<br>
dialects of the language via compiler switches. </blockquote><div><br>We already have `debug_assert`. I'm essentially proposing to turn 
overflow checks into `debug_assert`s. `debug_assert`s are something we 
already have, and not a new dialect.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I brought up the issue<br>
of macros and syntax extensions but you've chosen to ignore that.<br></blockquote><div><br></div><div>The assumption of bad faith is appreciated. I must have missed it accidentally. If there's an issue, I'd be interested to know about it.<br>
<br>Could you point out where you brought it up? A Ctrl-F over the thread finds the above comment as the only occurrence of the words "macro" and "extension".<br><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

<div><div class="h5"><br>
>  * For code where wraparound semantics is desired, the appropriate<br>
> facilities are also available.<br>
><br>
> Given the discussion so far, the design I'd be leaning toward to<br>
> accomplish the above might be something like this:<br>
><br>
>  * Two sets of fixed-sized integer types are available in the `prelude`.<br>
><br>
>  * `u8`..`u64`, `i8`..`i64`, `int`, and `uint` have unspecified results<br>
> on overflow (**not** undefined behavior). A compiler flag turns overflow<br>
> checks on or off. Essentially, the checks are `debug_assert`s, though<br>
> whether they should be controlled by the same flag is open to debate.<br>
><br>
>  * `uc8`..`uc64`, `ic8`..`ic64`, `intc`, and `uintc` are *always*<br>
> checked for overflow, regardless of flags. (Names are of course open to<br>
> bikeshedding.)<br>
><br>
>  * Given that these are not really different semantically, automatic<br>
> coercions between corresponding types can be considered. (Even then, for<br>
> `a + b` where `a: int` and `b: intc`, explicit disambiguation would<br>
> presumably still be required.)<br>
><br>
>  * Unbounded integer types using owned memory allocation are available<br>
> in the `prelude`. I might prefer to call them `Integer` and `Natural`<br>
> instead of `BigInt` and `BigUint`.<br>
><br>
>  * Types and/or operations which wrap around on overflow are available<br>
> in the standard library. Given how specialized the use cases for these<br>
> seem to be, perhaps they could even go directly in the `hash` module.<br>
> It's not clear to me yet whether a separate set of types (`uw8`..`uw64`,<br>
> `iw8`..`iw64`) or just a separate set of operations on the `prelude`<br>
> types (e.g. `trait WrappingAdd`) would be preferable.<br>
<br>
</div></div>A `Vec<u32>` and `Vec<uw32>` would be entirely distinct types. That<br>
alone is going to cause performance issues and will make the language<br>
more painful to use.</blockquote><div><br></div><div>That's a good point, and an argument in favor of different operators rather than different types. <br><br>(It's also something that would be solved by the `Coercible` trait.)<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> It's already pushing the boundaries of what people<br>
will be willing to accept with features like strictly checked move<br>
semantics and reference lifetimes.<br>
<div class=""><br>
>  * Unbounded integer types which use garbage collected allocation are<br>
> available in the `gc` module.<br>
<br>
</div>It doesn't sense to have 3 separate implementations of big integers for<br>
reference counting, atomic reference counting and task-local tracing<br>
garbage collection.<br></blockquote><div><br></div><div>Coincidentally, I didn't propose it. I proposed one implementation with owned allocation (which we already have) in the `prelude` and one with tracing GC allocation in the `gc` module.</div>
<div><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
<br>_______________________________________________<br>
Rust-dev mailing list<br>
<a href="mailto:Rust-dev@mozilla.org">Rust-dev@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/rust-dev" target="_blank">https://mail.mozilla.org/listinfo/rust-dev</a><br>
<br></blockquote></div><br></div></div>