-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Implement BitAnd-based truncation for integers #54442
Conversation
There are a variety of circumstances where a function wants to take n low bits from a generic input type. These implementations support that workflow. Closes rust-lang#54435
r? @sfackler (rust_highfive has picked a reviewer for you, use r? to override) |
Cross-type arithmetic/bitwise operations are generally not implemented for primitive types. Very often such type mismatch means an accidental mistake, and in that case the code author needs to harmonize operand types rather than get truncation performed implicitly. |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
I agree on keeping cross-type arithmetic/bitwise operations out of Rust, yet "as" casts could be slowly phased out and replaced by more specialized and generally more reliable conversions. So adding some specialized methods (distinct from the operators) to perform the truncations could be OK. |
This will make type interference not work right in some cases. Currently |
Smushing a few of the comments here together, maybe it would make sense to have explicitly-asymmetrical methods for some of these operations, to make the intent and asymmetrical type handling clearer? |
An explicit method would be dope. Furthermore, it doesn’t need to be a part of libstd proper and can be published as a crate instead. |
So, we already have |
@nagisa I disagree strongly. Rust's number system is so painful to use in generic contexts that we literally have a whole set of crates (rust-num*) just to try to make it workable. I completely agree that libstd should be kept small. But the types it provide need to be usable without requiring external dependencies. The current situation is that conversion between the integer types is common, but painful. Further, a good number of the useful methods/functions aren't in traits, so they can't be specified in a generic binding. |
This mostly true, but on the other hand languages that allow cross-type arithmetic/bitwise operations lead very quickly to programs that are soup of types. I see this very well when I convert C/C++/Java code to Rust. Most of that conversion pain is caused by the very wild typing of the original code and not by Rust strictness or by needs of the algorithms or by performance needs. This is another case where Rust strictness leads to (much) better code. |
@leonardo-m I agree. But this is solvable with the right traits and compiler support. The reason I list both is that we don't want a situation where common operations in a generic setting carry a performance penalty. For example, "cast to u8 and bitwise and" should emit a single instruction, not a function call. Here's what I see as needed improvements:
The above code should emit zero instructions on architectures with a zero register and one instruction otherwise. |
Also, the |
Why would it emit a function call? Inlining is performed extensively on Rust code for exactly this kind of situation. |
Also, trait exclusion...
|
@sfackler My full comment was clear I meant in a generic context. Currently, there is no way to perform a cast behind a generic. We will get closer when |
One example of what we should be able to write is this:
|
Why? |
@sfackler Run time error handling because |
Uh, sure, different operations have different performance characteristics. You can write |
@sfackler Not on stable. Not ever according to the docs. |
pub trait CastInto<T> {
fn cast_into(v: Self) -> T;
}
impl CastInto<u8> for u32 {
#[inline]
fn cast_into(v: u32) -> u8 {
v as u32
}
}
|
@sfackler I'm not questioning that. I'm suggesting that Rust consider stabilizing |
Maybe we should implement two traits: one for truncated conversion and one for size-equivalence conversion. Thus, For example, to convert a
|
A third party crate seems like a good place to design an API like that. |
|
Ping from triage! It seem to me that this PR is a somewhat fundamental change requiring an RFC or at least some additional discussion. As such I'm closing this as blocked for now. Please comment / re-open if you disagree. Thanks for you contribution! |
There are a variety of circumstances where a function wants to take n
low bits from a generic input type. These implementations support that
workflow.
Closes #54435