Skip to content
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

Simplify non_zero arbitrary impl #281

Merged
merged 1 commit into from Jan 6, 2023
Merged

Simplify non_zero arbitrary impl #281

merged 1 commit into from Jan 6, 2023

Conversation

ghost
Copy link

@ghost ghost commented Nov 16, 2022

No description provided.

Copy link
Member

@cameron1024 cameron1024 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, should have thought of that 🤦

@ghost
Copy link
Author

ghost commented Dec 2, 2022

The book warns that filtering doesn't interact well with shrinking. I wonder if these shouldn't be implemented by mapping 1.. ranges instead of filtering.

@cameron1024
Copy link
Member

I think that could work well for unsigned types.

As for signed types, I think we need to be careful about uniformity. IMO, NonZeroU64 should be equally likely to produce a 1 or a -1, but naively using prop_oneof would leave negative numbers slightly more common than they should be AFAICT. I think we would need to calculate the weights, but that would be tricky since prop_oneof expects weights to be a u32. For the case of NonZeroU64 (assuming I've done the maths right), we would need the weights to be 2^63 for the negative numbers and 2^63 - 1 for the positive numbers, both of which overflow a u32. And we couldn't simplify this, since 2^63 - 1 is prime.

It also looks like this u32 is part of the public API, so we can't easily change it. We may be able to replace it with a type parameter with u32 as a default (maybe N: Into(u128)), but that would potentially break type inference. This RFC has some guidance, but I don't think this issue is as simple as it might seem.

Or maybe I'm just getting hung up over uniformity. To me, it feels important, but maybe others disagree?

@ghost
Copy link
Author

ghost commented Dec 19, 2022

prop_oneof isn't needed. Just generate x: u64 from 1..u64::MAX and map it 1-1 into a NonZeroI64 with casting.

use std::num::{NonZeroI64};

fn main() {
    fn convert_wrapping(x: u64) -> NonZeroI64 {
        NonZeroI64::new(x as i64).unwrap()
    }
    
    assert_eq!(convert_wrapping(1), NonZeroI64::new(1).unwrap());
    assert_eq!(convert_wrapping((1 << 63) - 1), NonZeroI64::new(i64::MAX).unwrap());
    assert_eq!(convert_wrapping(1 << 63), NonZeroI64::new(i64::MIN).unwrap());
    assert_eq!(convert_wrapping(u64::MAX), NonZeroI64::new(-1).unwrap());
} 

@cameron1024
Copy link
Member

This is why I shouldn't do reviews late at night 😅thanks

@matthew-russo matthew-russo merged commit d666b7e into proptest-rs:master Jan 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants