-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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 Mul<u64> and Div<u64> for Duration #32515
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
Hm the breakage with unsuffixed literals indeed seems like a non-starter here. I wonder if it'd be worth investigating the underlying type inference bug? |
Not sure it's a bug strictly - there's no precedence on which integer type a literal should be if multiple apply and none are |
Can you fix the inference regression by implementing the ops for It seems to work (adds a warning though). |
I'd be a bit uncomfortable with that - |
@sfackler is correct that this isn't a bug. We made the decision to allow "input" types to a trait (like type parameters) influence type inference, which is often helpful, but can be brittle when you add new impls. It's possible that default type parameter fallback could help here, but I don't immediately see a route. This is a kind of API evolution we certainly should allow, but the interconnecting pieces are really tricky (and the future of even default param fallback is in question). So (1) I will take this example into consideration on the lang design front and (2) meanwhile, we should figure out a different route to gain this functionality. |
Bah oh well. An idea, though, perhaps? impl<T: Into<u64>> Mul<T> for Duration {
// ...
} Now that we have a number of |
@alexcrichton I tried plugging that into my test above, it doesn't really solve the problem. |
The libs team discussed this PR during triage and the decision was to merge with an inherent method of a name other than |
Due to inference issues, these unfortunately can't be Mul and Div impls :(
I updated the PR to move these to |
#[unstable(feature = "duration_u64", reason = "newly added", issue = "0")] | ||
pub fn div_u64(&self, rhs: u64) -> Duration { | ||
let secs = self.secs / rhs; | ||
let carry = self.secs - secs * rhs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this not simply let carry = self.secs % rhs;
?
AFAIK it requires either a muldiv-like operation (which would be the best option at least on x86), or Looks like one use case for rust-lang/rfcs#1504 |
@sfackler maybe this function can help? |
Ooh, nice, that looks like exactly what's needed! I'll update tonight. |
|
Hm can you clarify? The operation we want is
Which when substituted looks like:
Given that, where does |
The docs on mul_div_u64 state that it "Computes (value * numer) / denom without overflow, as long as both (numer*denom) and the overall result fit into i64 (which is the case for our time conversions)", since |
Ok, well I'm basically lost in the weeds of what's going on, is this blocked on landing until that's fixed? |
I think the best approach would probably be to add some intrinsics to have LLVM generate u64 * u64 -> u128 and u128 / u64 -> u64 logic for us. Doing it correctly by hand is really complex in the general case: https://github.com/sdroege/rust-muldiv/blob/master/src/u64_muldiv.rs but really simple on common architectures: https://github.com/sdroege/rust-muldiv/blob/master/src/u64_muldiv_x86_64.rs |
I created a time2 crate that adds these methods and a few others - https://github.com/sfackler/rust-time2. I think it makes more sense for it to bake out there for now and then move a larger set of functionality in later. |
This probably can't merge as-is because it breaks any code that
multiplies or divides a Duration by an unsuffixed literal :(
However, these operations are useful in many contexts (e.g. data
transfer estimation) where a u32 isn't big enough and the logic is
pretty complex, especially for multiplication. Hopefully we can expose
these in some way?
cc @rust-lang/libs
Any ideas on where to go with this functionality, @aturon?