4 ms·
I think a proper solution would be to expose the trait `IsZero` [0] as that is used to figure out when it is correct to use `calloc` instead of having to do `ma
by erk__ 5y ago
I think a proper solution would be to expose the trait `IsZero` [0] as that is used to figure out when it is correct to use `calloc` instead of having to do `malloc` -> `memset` [1].
I don't know if there is any plans for exposing that trait, but it would be a nice thing to see.
[0]: https://github.com/rust-lang/rust/blob/master/library/alloc/src/vec/is_zero.rs https://github.com/rust-lang/rust/blob/master/library/alloc/...
[1]: https://github.com/rust-lang/rust/blob/master/library/alloc/src/vec/spec_from_elem.rs#L50..L60 https://github.com/rust-lang/rust/blob/master/library/alloc/...
- conradludgate 5y agoI think you don't need an IsZero trait. It needs to know if the bytes are zero. A custom implementation of IsZero might not hold that guarantee. However, if the type is Copy and all the bytes are zeros, then you know it can be calloc
- Measter 5y agoYou mean by checking the bytes of the data directly kinda like in this godbolt example: https://godbolt.org/z/78cvfshva https://godbolt.org/z/78cvfshva
- tialaramex 5y ago(As you likely know) Normally in Rust the trait is a gentleman's agreement. If my type does not have total Equivalence then I don't implement the Eq trait, and so if a type has Eq then it's promising to deliver total Equivalence. You can, in fact, just defy this and make types that do something "completely wrong" while implementing the syntax of the Trait and I provide a suite of them so that other people don't need to do that experiment: https://crates.io/crates/misfortunate https://crates.io/crates/misfortunate However, Rust does have two other tricks up its sleeve: 1. Unsafe traits. You can declare a trait to be "unsafe". Implementations of this trait likewise need that "unsafe" keyword and it alerts the programmer that, as with unsafe function calls, they are responsible for actually getting the implementation details correct. Not many standard library traits are unsafe because that's a considerable burden, but a few are, including Send and Sync. You wouldn't learn much by implementing unsafe traits wrongly in a library like misfortunate, it's the same lesson as a C++ library that scribbles on random memory addresses. 2. Rust knows whether you implemented a trait by hand or merely derived it. In a few cases it can be reasonable for the language to distinguish these cases for built-in traits, since in the former case it knows the derived trait does what is needed even though a manual implementation may not. It is possible that future improvements to Const Generics will rely on this latter idea. So long as you derive Eq rather than implementing it, Rust can reason that your type really is suitable as a constant type parameter whereas misfortunate::Always is not suitable (it would cause mayhem if permitted because of its idea of what "equality" is) despite claiming to be Eq.
- conradludgate 5y agoGood idea with unsafe traits. Maybe something like unsafe trait IsZero: Copy { fn is_zero(&self) -> bool; } #[derive(Copy, IsZero)] struct Foo { a: u8, b: u16, } which could derive into unsafe impl IsZero for Foo { fn is_zero(&self) -> bool { true && self.a.is_zero() && self.b.is_zero() } }
- conradludgate 5y agoThere needs to be some thought into how it works with Enums too. Rust currently has no built in standard for enum defaults (you have to implement default yourself). It would be nice to somehow mark one of the variants to be represented with the 0 discriminant (Like how Option::None is implemented)
- estebank 5y agoThe RFC for that has been recently accepted[1] and the implementation is already available in nightly[2]. [1]: https://rust-lang.github.io/rfcs/3107-derive-enum-default.html https://rust-lang.github.io/rfcs/3107-derive-enum-default.ht... [2]: https://github.com/rust-lang/rust/pull/86735 https://github.com/rust-lang/rust/pull/86735
- conradludgate 5y agoUnfortunately there's still no guarantee for which variant will be represented by 0
- erk__ 5y agoYou may also have cases where no variant is 0 so this case is probably not as straightforward
- estebank 5y agoThe comment is fair. There have been some talks about being able to allow end users specify niches so that if you could have something like enum E<T> { Empty = 42, Some(NonFortyTwo<T>), } in the same way that the following is of size T today enum E<T> { Empty = 0, Some(NonZero<T>), } but that's not possible today.
- the8472 5y ago> However, if the type is Copy and all the bytes are zeros, then you know it can be calloc That's not as easy to check as one would think since Copy types can still contain uninitialized bytes.
- PoignardAzur 5y agoYeah, but in the common case all the uninitialized bytes are in the padding at the end of the struct (since Rust can re-arrange fields). Especially in a case like in the article, where the type is very small (one byte), and the obstacle is that the author is using a newtype.
- the8472 5y agoKnowing that they usually are at the end doesn't help since you still need to write a general runtime check that expresses "are all the bits for this type zero or uninit". Afaik currently there is no way to do this without causing UB. This would need some new intrinsic.