-
Notifications
You must be signed in to change notification settings - Fork 20
ACP: Unchecked construction of core::time::Duration
#117
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
Comments
I would use this API if it existed for conversions provided by the |
Well, that could also be solved by a |
A fn durations() {
let x = time::Duration::new(100, 0); // static analysis rejection: call to function that might panic
let y = time::Duration::new_checked(100, 0).unwrap(); // ditto
} |
For For arbitrary inputs, how are you going to ensure correctness without any checks at all? I.e. where does one get inputs that are already correctly split into seconds (bounded) nanos from without doing some checking and error-handling? Apparently not even operating system APIs can get their own guarantees right and need to be sanitized: rust-lang/rust#108277 Note that getting these values wrong is instant UB because the nanosecond field has range information that is used in optimizations. C's |
A quick search of the uses where I am constructing
I haven't checked the assembly resulting for these, but I suspect that it is not optimized out as rustc doesn't know about the validity requirements of |
@jmillikin For a result-returning |
We discussed this during today's libs-API meeting. We're more in favor of adding |
Marking this as accepted on the assumption that |
core::time::Duration
core::time::Duration
This might be my own lack of skill, but I haven't been able to get Both of these functions compile to the same assembly on x86_64 with v1.78.0 and fn duration_new_unchecked(secs: u64, nanos: u32) -> Duration {
let d = Duration::new_checked(secs, nanos);
unsafe { d.unwrap_unchecked() }
}
fn duration_new_unchecked(secs: u64, nanos: u32) -> Duration {
if let Some(x) = Duration::new_checked(secs, nanos) {
return x;
}
unsafe { std::hint::unreachable_unchecked() }
} duration_new_unchecked:
mov edx, esi
mov rax, rdi
cmp esi, 1000000000
jb .LBB0_2
mov ecx, edx
shr ecx, 9
imul rcx, rcx, 281475
shr rcx, 39
imul esi, ecx, 1000000000
sub edx, esi
add rax, rcx
.LBB0_2:
ret Most of those instructions are to handle the case of the It is possible to define a function that does compile to the expected assembly, by forcefully rejecting the possibility of nanosecond overflow -- this is what I would expect the fn duration_new_unchecked_v2(secs: u64, subsec_nanos: u32) -> Duration {
const NANOS_PER_SEC: u32 = 1_000_000_000;
if subsec_nanos >= NANOS_PER_SEC {
unsafe { std::hint::unreachable_unchecked() }
}
Duration::new(secs, subsec_nanos)
} (stub asm, which would presumably be inlined to achieve a free conversion from duration_new_unchecked_v2:
mov edx, esi
mov rax, rdi
ret |
Tracking issue: rust-lang/rust#125748 Initial implementation: rust-lang/rust#125749 The impl PR contains both |
The assembly is panic-free. It doesn't show that the few extra, non-taken instructions affect any real applications. |
Ah, your PR is doing the extra carry, yes, an |
Ah, yeah, I thought it would be confusing if If the implementation looked like this: fn new_checked(secs: u64, subsec_nanos: u32) -> Option<Duration> {
if subsec_nanos >= NANOS_PER_SEC {
return None;
}
Some(Duration { secs, nanos: unsafe { Nanoseconds(subsec_nanos) } })
} Then So I guess the unasked question is which semantics for |
If confusion with new is a concern it could be named |
core::time::Duration
core::time::Duration
Just to clarify: regardless of the presence or signature of If not, then it would be better to remove the "accepted" tag, and I'll close this out. Someone who has a need for it might file an ACP for |
Uh oh!
There was an error while loading. Please reload this page.
Proposal
Problem statement
Constructing a
core::time::Duration
with sub-second resolution currently forces the programmer to choose between two unappealing options:Duration::new()
, which is allowed to panic.Duration::from_secs()
and thensaturating_add()
the nanoseconds, which is relatively expensive.This proposal would add an unsafe constructor that performs no checking or math.
Motivation, use-cases
When interacting with C APIs that consume or return a
struct timespec
, it would be useful to have free conversion tocore::time::Duration
.When writing code that is not allowed to panic, it would be useful to have a way to construct
core::time::Duration
values from known-good inputs.Solution sketches
Links and related work
n/a
What happens now?
This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.
The text was updated successfully, but these errors were encountered: