Skip to content

Add new traits for reference and assignment operators #283

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

Merged
merged 2 commits into from
May 7, 2017

Conversation

cuviper
Copy link
Member

@cuviper cuviper commented Apr 24, 2017

There are two new "utility" traits covering the basic operators:
Add, Sub, Mul, Div, and Rem.

  • NumOps<Rhs, Output>: operators with an arbitrary operand and output.
  • NumAssignOps<Rhs>: assignment operators with an arbitrary operand.

Then the new collection of numeric traits are:

  • Num: effectively unchanged, just taking operands by value.
  • NumRef: Num adding reference operands on the right side.
  • RefNum: &T operators, with either T or &T on the right side.
  • NumAssign: Num adding assignment operators by value.
  • NumAssignRef: NumAssign adding reference assignment operators.
    • Nothing actually implements this yet!

Acknowledgement: this is roughly based on @andersk's suggestion.

/// second operand either by value or by reference.
///
/// This is automatically implemented for all `&T` implementing the operators.
pub trait RefNum<Base>: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
Copy link
Member Author

Choose a reason for hiding this comment

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

I don't like taking the Base type as a parameter, but I didn't find a better way to do this. I tried adding a Deref constraint, but the compiler didn't seem to see that <Self as Deref>::Target always matches the types we want, especially when chaining as in the check_refnum_ops test.

///
/// This is automatically implemented for all `&T` implementing the operators.
pub trait RefNum<Base>: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
impl<'a, T> RefNum<T> for &'a T where &'a T: NumOps<T, T> + for<'r> NumOps<&'r T, T> {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Why limit this impl to &T, rather than everything satisfying the trait constraints?

impl<Base, T> RefNum<Base> for T where T: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}

Copy link
Member Author

Choose a reason for hiding this comment

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

In part, because I was hoping to find a way not to need the Base parameter at all. I'm stuck on that though.

I also think it's a little weird that Base = T would be allowed, as I'm trying to specify a reference type here. I was going for NumRef for values with numeric operators, and RefNum for references with numeric operators. Maybe that distinction isn't so useful? I'm not sure...

I probably could narrow it with RefNum<Base>: Deref<Target = Base> + ...

Copy link
Member Author

Choose a reason for hiding this comment

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

The more I think about it, the more I like adding Deref in there, to lock down the intended relationship between T and Base. If I can't get rid of Base, at least I can make it have only one possible answer -- Base = <T as Deref>::Target.

Copy link
Contributor

Choose a reason for hiding this comment

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

I can’t seem to make it work without the Base parameter either. This may be an inference bug. But unless Base can actually be avoided, such narrowing seems to add nothing to the present use case—in for<'a> &'a T: RefNum<T>, we don’t need to tell the compiler again that &'a T is a reference—and it might exclude other use cases we haven’t thought of.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm trying to think if there are hypothetical situations where you'd want a clear distinction between RefNum and NumRef. Maybe for specialization? But I think you could use private traits with a Deref or similar differentiator. Dunno.

I'll play a little more, and as long I can't find any problem doing it your way, I'll switch it.

Thanks for your input!

+ Mul<Rhs, Output = Output>
+ Div<Rhs, Output = Output>
+ Rem<Rhs, Output = Output>
{}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can Output be made into an associated type here? (I’m having trouble getting that to work, though.)

Copy link
Member Author

Choose a reason for hiding this comment

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

I can't find a way to specify that an associated Output and all the individual ops' Output must be identical. If you figure it out, let me know...

@cuviper
Copy link
Member Author

cuviper commented Apr 25, 2017

OK, I switched to a more generic impl for RefNum.

@cuviper
Copy link
Member Author

cuviper commented Apr 29, 2017

I'll merge this in a day or two if there are no further comments...

@cuviper
Copy link
Member Author

cuviper commented May 7, 2017

@homu r+

@homu
Copy link
Contributor

homu commented May 7, 2017

📌 Commit 68028d5 has been approved by cuviper

@homu
Copy link
Contributor

homu commented May 7, 2017

🔒 Merge conflict

@homu
Copy link
Contributor

homu commented May 7, 2017

☔ The latest upstream changes (presumably #286) made this pull request unmergeable. Please resolve the merge conflicts.

cuviper added 2 commits May 6, 2017 21:35
There are two new "utility" traits covering the basic operators:
`Add`, `Sub`, `Mul`, `Div`, and `Rem`.

- `NumOps<Rhs, Output>`: operators with an arbitrary operand and output.
- `NumAssignOps<Rhs>`: assignment operators with an arbitrary operand.

Then the new collection of numeric traits are:

- `Num`: effectively unchanged, just taking operands by value.
- `NumRef`: `Num` adding reference operands on the right side.
- `RefNum`: `&T` operators, with either `T` or `&T` on the right side.
  - This does not specify `T: Num`, as rust-lang/rust#20671 means that
    could only add a constraint, without implying its presence for use.
- `NumAssign`: `Num` adding assignment operators by value.
- `NumAssignRef`: `NumAssign` adding reference assignment operators.
  - Nothing actually implements this yet!

Acknowledgement: this is roughly based on [@andersk's suggestion][1].

[1] rust-num#94 (comment)
@cuviper
Copy link
Member Author

cuviper commented May 7, 2017

@homu r+

@homu
Copy link
Contributor

homu commented May 7, 2017

📌 Commit 3ead4a1 has been approved by cuviper

@homu
Copy link
Contributor

homu commented May 7, 2017

⌛ Testing commit 3ead4a1 with merge f9d36e6...

homu added a commit that referenced this pull request May 7, 2017
Add new traits for reference and assignment operators

There are two new "utility" traits covering the basic operators:
`Add`, `Sub`, `Mul`, `Div`, and `Rem`.

- `NumOps<Rhs, Output>`: operators with an arbitrary operand and output.
- `NumAssignOps<Rhs>`: assignment operators with an arbitrary operand.

Then the new collection of numeric traits are:

- `Num`: effectively unchanged, just taking operands by value.
- `NumRef`: `Num` adding reference operands on the right side.
- `RefNum`: `&T` operators, with either `T` or `&T` on the right side.
  - This does not specify `T: Num`, as rust-lang/rust#20671 means that
    could only add a constraint, without implying its presence for use.
- `NumAssign`: `Num` adding assignment operators by value.
- `NumAssignRef`: `NumAssign` adding reference assignment operators.
  - Nothing actually implements this yet!

Acknowledgement: this is roughly based on [@andersk's suggestion](#94 (comment)).
@homu
Copy link
Contributor

homu commented May 7, 2017

☀️ Test successful - status

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.

3 participants