-1

When I do

seq += u64::from(rhs);

Everything works. But I'd prefer the syntax of rhs.into() with that I'm currently getting,

error[E0283]: type annotations needed
  --> src/sequence.rs:50:5
   |
19 | seq += rhs.into();
   |     ^^ ---------- this method call resolves to `T`
   |     |
   |     cannot infer type for type parameter `T`
   |
   = note: cannot satisfy `_: Into<u64>`
   = note: required because of the requirements on the impl of `AddAssign<_>` for `Sequence`

This .into() syntax normally works. Why doesn't type inference work on binary operators += such that if the LHS only implements AddAssign<u64> the RHS will coerce? And moreover, aside from using from what is the syntax (if possible) to provide this type information to .into that the compiler needs? I've tried things like .into::<u64>(rhs) and that also doesn't work.


I am implementing AddAssign like this,

impl<T: Into<u64>> AddAssign<T> for Sequence {
  fn add_assign(&mut self, rhs: T) {...}
}

And From like this,

impl From<Sequence> for u64 {
  fn from(seq: Sequence)-> u64 { ... }
}
Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • _what is the syntax (if possible) to provide this type information to .into that the compiler needs?_ `Into::::into(rhs)` – Ömer Erden Sep 23 '21 at 16:20
  • Oh that's nifty. I tried `.into::(rhs)` and a bunch of other premutations which didn't work. Would you be able to answer with that and perhaps explain into `Into::into(rhs)` is different syntactically from `.into::(rhs)`? – Evan Carroll Sep 23 '21 at 16:22
  • 1
    Generic type parameter belongs to trait in here not the function – Ömer Erden Sep 23 '21 at 16:23

1 Answers1

1

You have a double Into indirection, probably by mistake. Since your type already implements AddAssign<T> where T: Into<u64>, then there is no need to add .into() to your right-hand member. It should be expected that the implementation of add_assign (not provided in your example) would call into underneath.

seq += rhs;

In fact, adding it would only bring ambiguity, because then the compiler was being told to call Into<X>::into(rhs) on a type X which is never mentioned nor constrained anywhere. The only constraint would be Into<u64>, but multiple types fulfill it.

A complete example:

use std::ops::AddAssign;

struct Sequence;

impl<T: Into<u64>> AddAssign<T> for Sequence {
    fn add_assign(&mut self, rhs: T) {
        let value: u64 = rhs.into();
        // use value
    }
}

fn main() {
    let mut x = Sequence;
    x += 6_u32;
}

what is the syntax (if possible) to provide this type information to .into that the compiler needs?

Again, this is not needed. But that would be possible with the so-called fully qualified syntax.

See also:

E_net4
  • 27,810
  • 13
  • 101
  • 139
  • Wow, now I feel dumb. Yeah, just leaving out the `.into` works. In other news, you're better at this than `cargo check`. – Evan Carroll Sep 23 '21 at 16:30
  • I filed this as an improvement: https://github.com/rust-lang/rust/issues/89204 – Evan Carroll Sep 23 '21 at 16:39
  • @EvanCarroll I am pretty sure that error message is fine, there can be other scenarios where you can use multiple `into`s, I thought you were trying to use it like that in the first place ^^ , please note that `Into` implementations are not transitive. – Ömer Erden Sep 23 '21 at 17:10