As it turns out, using u64 for Duration::from_nanos isn't the greatest idea because 2^64 / 1,000,000,000 / 60 / 60 / 24 / 365 comes out to 585 years which is rather short. I don't think the libs team realized how short this was when stabilizing it, but fortunately it hasn't actually hit stable yet and is still in beta so we have the time to reconsider that decision.
cc @SimonSapin who kicked off stabilization in https://github.com/rust-lang/rust/issues/46507
It's not clear if we may actually hit that limit. Filesystem like ext4, btrfs has nano second level timestamps but they are both capped at 64 bits.
One possible use case though, may be scientific emulation where this can potentially be a problem; but I don't actually do such emulations so I have no further ideas.
@retep998, what do you think of keeping it stable but changing the argument to u128 in beta?
CC @rust-lang/libs
I would prefer to keep it as u64. We provide other constructors for dealing with large durations, such as Duration::new. Ordinary overflow checks should catch when somebody multiplies numbers for a from_nanos argument and it overflows.
It's not clear if we may actually hit that limit. Filesystem like ext4, btrfs has nano second level timestamps but they are both capped at 64 bits.
Meanwhile on Windows NTFS has 64bit timestamps that are multiples of 100ns, which can overflow a u64 from_nanos.
@SimonSapin Changing the argument to u128 means the conversion can fail, since Duration stores seconds in an u64 (and this is effectively exposed in stable, infallible APIs like as_secs) and 2^128 is much larger than 2^64 * NANOS_PER_SEC. So it would not be a simple search-and-replace job but require some redesign as well (if it's feasible at all, we may not want the convenience constructor to be fallible).
I agree with @dtolnay in that we've got other constructors for dealing with overflow or larger durations, so having this as a convenience constructor seems like it should be good to do still.
I also prefer a u64 argument.
I find it convincing that converting an NTFS timestamp to a Duration is better served by a few lines of arithmetic and Duration::new. How does that sound, @retep998?
Another point. If we ever add methods like as_nanos that return a u128, the user wouldn't be able to immediately pass that value back to from_nanos.
The consensus from the libs team seems to be to keep using u64, right? 1.27.0 is approaching.
@pietroalbini I believe so, yes.
Well, this can be closed then.
I guess it's too late, but IMO a compelling argument for that change would have been that Duration::from_nanos(d.as_nanos()) does not compile.
That said, now that it's stable, I guess changing it even in a new edition would basically not be doable?
Most helpful comment
@SimonSapin Changing the argument to u128 means the conversion can fail, since Duration stores seconds in an u64 (and this is effectively exposed in stable, infallible APIs like
as_secs) and 2^128 is much larger than 2^64 *NANOS_PER_SEC. So it would not be a simple search-and-replace job but require some redesign as well (if it's feasible at all, we may not want the convenience constructor to be fallible).