Is not being able apply abs() without explicit types a limitation of type inference?

Consider the code below:

pub fn main() {
    let data = [
        [-200, 100],
        [-300, 110],
        [50, 120],
        [-400, 150],
        [600, 80],
    ];

  let s = data[0][0];
  let q = data[1][0];
  println!("{}", s.abs().max(q.abs()));
}

It fails with:

error[E0599]: no method named `abs` found for type `{integer}` in the current scope
  --> src/main.rs:12:20
   |
12 |   println!("{}", s.abs().max(q.abs()));
   |                    ^^^

error[E0599]: no method named `abs` found for type `{integer}` in the current scope
  --> src/main.rs:12:32
   |
12 |   println!("{}", s.abs().max(q.abs()));
   |                                ^^^

error: aborting due to 2 previous errors

But when I add explicit types when declaring data, it works!

pub fn main() {
    let data: [[i32; 2]; 5] = [ // Type is explicitly specified
        [-200, 100],
        [-300, 110],
        [50, 120],
        [-400, 150],
        [600, 80],
    ];

  let s = data[0][0];
  let q = data[1][0];
  println!("{}", s.abs().max(q.abs()));
}

My initial thinking is this behavior is on account of some limitations of the type-inference system. If that indeed is the case, may be we could provide little more context in the error, say, "unable to infer granular type of integer"?

On the other hand, if this could be addressed that will be great as the behavior is somewhat unintuitive.

$ rustc -V
rustc 1.36.0 (a53f9df32 2019-07-03)

I think in the case of abs() specifically it's more difficult due to the edge case making it have different behavior based on the specific type: if the signed integer type resolves to an i8, (-128).abs() will panic, but if it resolves to i16 it won't. It can't know what behavior you want.

1 Like

So may be the error message in that case can be improved? Assuming {integer} is sort of parent type of u8|16|32.... (newbie this side - not at all familiar with the type-system), we output a hint if a method on parent is absent but is present on one of the child types.

Yes, it is a type inference limitation, a rather long-standing one. Per RFC 212, this should default to i32. The following issue which is now more than 4 years old has a discussion:

https://github.com/rust-lang/rust/issues/23545

On the other hand, this is also "working as designed", as Niko said on the issue. It is "a common source of annoyance", and "ground-up rewrite of typeck" to solve the issue was planned but never happened.

1 Like

In the long term, there should be no error. On the other hand, in the short term, I agree there should be a diagnostics issue to improve the error message. There must be an existing issue (this is long standing and kind of well known), but I can't find one now, so I think it is worthwhile to file an issue.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.