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

Add WrappingNeg trait #153

Merged
merged 3 commits into from
Mar 6, 2020
Merged

Add WrappingNeg trait #153

merged 3 commits into from
Mar 6, 2020

Conversation

ocstl
Copy link
Contributor

@ocstl ocstl commented Feb 5, 2020

Closes #10

A quick search turned up that the extprim implements PrimInt for its u128 and i128, but, since both have their own wrapping_neg method, it's a non-issue.

That being said, I don't know for certain that it is the only project that implements PrimInt, so it might be wise to wait for a larger version bump before merging this.

@cuviper
Copy link
Member

cuviper commented Feb 5, 2020

Thinking about #10 again -- we don't have any other "wrapping" methods on PrimInt, so I'm not sure why we would add wrapping_neg in particular. See also #95.

However, we do have WrappingAdd etc. -- so how about adding WrappingNeg?

@cuviper
Copy link
Member

cuviper commented Feb 5, 2020

A quick search turned up that the extprim implements PrimInt for its u128 and i128, but, since both have their own wrapping_neg method, it's a non-issue.

Note that while they do have an inherent wrapping_neg method, they would still be broken by a new PrimInt with that method until they add it to their implementation explicitly.
(Rust doesn't use structural typing for traits, the way Go does for interfaces.)

@ocstl
Copy link
Contributor Author

ocstl commented Feb 5, 2020

Note that while they do have an inherent wrapping_neg method, they would still be broken by a new PrimInt with that method until they add it to their implementation explicitly.
(Rust doesn't use structural typing for traits, the way Go does for interfaces.)

I thought I had tested for it, but you made me realise where I made a mistake. Thank you!

Thinking about #10 again -- we don't have any other "wrapping" methods on PrimInt, so I'm not sure why we would add wrapping_neg in particular. See also #95.

However, we do have WrappingAdd etc. -- so how about adding WrappingNeg?

It did feel a bit odd. And thanks for pointing out #95, it puts things in context.

The potential issue with adding WrappingNeg is that Neg was only implemented for Wrapping in Rust 1.10. Wouldn't this create a problem with regards to maintaining compatibility with 1.8?

@cuviper
Copy link
Member

cuviper commented Feb 6, 2020

The potential issue with adding WrappingNeg is that Neg was only implemented for Wrapping in Rust 1.10. Wouldn't this create a problem with regards to maintaining compatibility with 1.8?

I think it will be OK if we follow the style of the others:

impl<T: WrappingNeg> WrappingNeg for Wrapping<T>
where
    Wrapping<T>: Neg<Output = Wrapping<T>>,
{
    fn wrapping_neg(&self) -> Self {
        Wrapping(self.0.wrapping_neg())
    }
}

That where constraint just won't match anything before Rust 1.10. As written, it's not actually using <Wrapping<T> as Neg>::neg at all, so this is overconstrained, but it's what we have on the others. 🤷‍♂️

@ocstl ocstl changed the title int: add wrapping_neg method to PrimInt Add WrappingNeg trait Feb 6, 2020
@ocstl
Copy link
Contributor Author

ocstl commented Feb 6, 2020

One thing about this implementation that bugs me a bit is that the WrappingNeg trait can't be bound on Neg, since that trait is not implemented for the unsigned types, for (in retrospect) obvious reasons. This breaks with the style for the other Wrapping traits.

That where constraint just won't match anything before Rust 1.10. As written, it's not actually using <Wrapping as Neg>::neg at all, so this is overconstrained, but it's what we have on the others.

That is good to know, thank you!

I didn't see it coming, but turns out the absence of the Neg trait for Wrapping in Rust 1.8 is causing issues for testing though. I guess a workaround would be to use Sub instead (Wrapping(0_u8) - Wrapping(...)), but this seems unsatisfactory.

While it would be great to be able to close this issue, if you feel any discomfort qualms at all about this, don't hesitate to say so.

@ocstl
Copy link
Contributor Author

ocstl commented Feb 7, 2020

One thing about this implementation that bugs me a bit is that the WrappingNeg trait can't be bound on Neg, since that trait is not implemented for the unsigned types, for (in retrospect) obvious reasons. This breaks with the style for the other Wrapping traits.

Since CheckedNeg isn't bound by Neg either, this is fine. I tried to maintain the same order of operations as the Checked traits to make comparisons easier.

I also fixed a slight formatting issue.

The test for Wrapping falls back on Sub for the time being for lack of a better idea, although it does work for versions including 1.10 and above; I added a FIXME in case Neg becomes available following a MSRV change.

Thank you for your time, and let me know if there's anything. I was a bit too optimistic here.

Some WrappingNeg tests rely on core::ops::Neg being implemented for
core::num::Wrapping<_>. Since it was only added in Rust 1.10, this
causes the build to fail for version 1.8 (the MSRV).

The problematic tests have been replaced with a TODO. Ideally, if and
when the MSRV reaches 1.10, it will be a simple matter of reverting this
commit to bring back the tests.
@ocstl
Copy link
Contributor Author

ocstl commented Feb 10, 2020

Sorry for the stream-of-thought like nature of the previous comments.

That where constraint just won't match anything before Rust 1.10. As written, it's not actually using <Wrapping as Neg>::neg at all, so this is overconstrained, but it's what we have on the others.

This creates a bit of a problem for the wrapping_is_wrappingneg() test function, since in Rust 1.8, Wrapping is not WrappingNeg, although it is once we reach 1.10. This bothered me a bit, but I guess that since Neg is not implemented for Wrapping over all covered versions, this is not something one can guarantee to users.

Also, Since Neg was only implemented in 1.10, we can't actually test the Neg op (-Wrapping(255u8)). I replaced both of these tests with a TODO in a separate commit. This way, if the MSRV reaches 1.10, it's a simple matter of reverting it to bring back the tests.

Alternatively, if you'd rather tabled implemented WrappingNeg if and when the MSRV reaches 1.10 so both tests can be included, I would understand completely.

This legacy business is tricky. So, thank you for your hard work. 🙇‍♂️

@cuviper
Copy link
Member

cuviper commented Mar 6, 2020

I added a little bit to the doc example, but otherwise I think this is good, thanks!

bors r+

@bors
Copy link
Contributor

bors bot commented Mar 6, 2020

Build succeeded

@bors bors bot merged commit 1eb80e1 into rust-num:master Mar 6, 2020
@ocstl ocstl deleted the wrapping-neg branch March 7, 2020 16:00
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.

Wrapping neg is not implemented for PrimInt
2 participants