Weird integer inference failure

2e19741
Opened by Simonas Kazlauskas at 2024-12-21 05:10:31
const K: u64 = 8;
const P0: [u64; 6] = [2, 3, 7, 9, 10, 14];

fn main() {
    let mut ps = Vec::from(&P0 as &[_]);
    // Fixup P0 if necessary.
    for p in &mut ps {
        if *p == K {
            if *p == 2 || *p == 9 {
                *p -= 1;
            } else {
                *p += 1;
            }
        }
    }
    println!("{:?}", ps);
}

fails to compile, despite compiler figuring out that ps: Vec<u64>, but explicit annotation of the vector type is necessary for integers to be inferred correctly:

…
    // either works
    let mut ps: Vec<u64> = Vec::from(&P0 as &[_]);
    let mut ps = Vec::from(&P0 as &[u64]);
…

I would expect all the code snippets to be equivalent and compile.

  1. The compiler does not figure out that ps: Vec<u64> - casts only run after defaults.

    Ariel Ben-Yehuda at 2016-05-24 17:40:12

  2. It eventually does because the error messages explicitly mention the type of the element (u64). Perhaps it would be a good idea to move integer defaulting to later stage? I’m not familiar with that part of code either way.

    Simonas Kazlauskas at 2016-05-24 18:07:19

  3. The compiler does end up equating the element type of P0 and _, but only after integer fallback when we are checking casts. I don't think we can change this behavior backwards compatibly, we're pretty much committed to doing fallback before casts.

    Maybe what you want is for the compiler to use the fact that u64 is the only possible value of _ in that cast, but that's not a good idea because we may add new coercions and ways to cast things in the future. So this seems to be working as designed.

    Leonardo Yvens at 2018-06-01 19:33:18

  4. Current error

    error[[E0277]](https://doc.rust-lang.org/stable/error_codes/E0277.html): can't compare `u64` with `i32`
     --> src/main.rs:9:19
      |
    9 |             if *p == 2 || *p == 9 {
      |                   ^^ no implementation for `u64 == i32`
      |
      = help: the trait `PartialEq<i32>` is not implemented for `u64`
      = help: the trait `PartialEq` is implemented for `u64`
    
    error[[E0277]](https://doc.rust-lang.org/stable/error_codes/E0277.html): can't compare `u64` with `i32`
     --> src/main.rs:9:30
      |
    9 |             if *p == 2 || *p == 9 {
      |                              ^^ no implementation for `u64 == i32`
      |
      = help: the trait `PartialEq<i32>` is not implemented for `u64`
      = help: the trait `PartialEq` is implemented for `u64`
    
    error[[E0277]](https://doc.rust-lang.org/stable/error_codes/E0277.html): cannot subtract-assign `i32` from `u64`
      --> src/main.rs:10:20
       |
    10 |                 *p -= 1;
       |                    ^^ no implementation for `u64 -= i32`
       |
       = help: the trait `SubAssign<i32>` is not implemented for `u64`
       = help: the following other types implement trait `SubAssign<Rhs>`:
                 <u64 as SubAssign<&u64>>
                 <u64 as SubAssign>
    
    error[[E0277]](https://doc.rust-lang.org/stable/error_codes/E0277.html): cannot add-assign `i32` to `u64`
      --> src/main.rs:12:20
       |
    12 |                 *p += 1;
       |                    ^^ no implementation for `u64 += i32`
       |
       = help: the trait `AddAssign<i32>` is not implemented for `u64`
       = help: the following other types implement trait `AddAssign<Rhs>`:
                 <u64 as AddAssign<&u64>>
                 <u64 as AddAssign>
    
    For more information about this error, try `rustc --explain E0277`.
    

    Dylan DPC at 2023-05-30 10:12:49