Repository: rust
Issue: Integer literal type inference causes weird behavior including strange compiler diagnostic (but the suggestion is working).
Labels: A-diagnostics,T-compiler,A-inference,C-discussion,T-types

### Code

```Rust
use std::ops::Mul;

struct Stuff{
    a: i128
}


impl Mul<i64> for Stuff {
    type Output = Stuff;
    fn mul (self, other: i64) -> Stuff {
        Stuff{a: self.a * (other as i128)}
    }
}
impl Mul<i32> for Stuff {
    type Output = Stuff;
    fn mul (self, other: i32) -> Stuff {
        Stuff{a: self.a * (other as i128)}
    }
}


fn main() {
    let stuff = Stuff{a: 42};

    let y = stuff * 2; // Note: if I specify y's type or 2's type, it compiles.

    println!("{:?}", y.a);
}
```


### Current output

```Shell
error[E0282]: type annotations needed
  --> src/main.rs:25:9
   |
25 |     let y = stuff * 2;
   |         ^
26 |     
27 |     println!("{:?}", y.a);
   |                      - type must be known at this point
   |
help: consider giving `y` an explicit type
   |
25 |     let y: /* Type */ = stuff * 2;
   |          ++++++++++++

For more information about this error, try `rustc --explain E0282`.
```


### Desired output

It should compile.


### Rationale and extra context

Following https://doc.rust-lang.org/reference/expressions/literal-expr.html#integer-literal-expressions I think the compiler should be able to infer that `2` is an `i32` and compile my program.

Alternatively, regardless of `2`'s type, `y` can only be a `Stuff`, so this precision should be unnecessary and the compiler should compile my program.

### Other cases

The following modifications compile:

* The program modified according to the compiler's suggestion (adding `Stuff` as `y`'s type). (code below)
* Displaying `y` instead of `y.a`. (code below)
* Changing `2` to `2i32` or `2i64`. (no code below)
 
The compiler suggestion (compiles):
```Rust
use std::ops::Mul;

struct Stuff{
    a: i128
}


impl Mul<i64> for Stuff {
    type Output = Stuff;
    fn mul (self, other: i64) -> Stuff {
        Stuff{a: self.a * (other as i128)}
    }
}
impl Mul<i32> for Stuff {
    type Output = Stuff;
    fn mul (self, other: i32) -> Stuff {
        Stuff{a: self.a * (other as i128)}
    }
}


fn main() {
    let stuff = Stuff{a: 42};

    let y: Stuff = stuff * 2; // This is the change the compiler suggests, and it works.

    println!("{:?}", y.a);
}
```

Displaying `y` instead of `y.a` (compiles too):
```Rust
use std::ops::Mul;

#[derive(Debug)] // First change in this code snippet
struct Stuff{
    a: i128
}


impl Mul<i64> for Stuff {
    type Output = Stuff;
    fn mul (self, other: i64) -> Stuff {
        Stuff{a: self.a * (other as i128)}
    }
}
impl Mul<i32> for Stuff {
    type Output = Stuff;
    fn mul (self, other: i32) -> Stuff {
        Stuff{a: self.a * (other as i128)}
    }
}


fn main() {
    let stuff = Stuff{a: 42};

    let y = stuff * 2;

    println!("{:?}", y); // 2nd change, I display y instead of y.a
}
```


### Rust Version

```Shell
rustc 1.80.1 (3f5fd8dd4 2024-08-06)
binary: rustc
commit-hash: 3f5fd8dd41153bc5fdca9427e9e05be2c767ba23
commit-date: 2024-08-06
host: x86_64-unknown-linux-gnu
release: 1.80.1
LLVM version: 18.1.7
```


### Anything else?

It also causes the same compiler diagnostic on 1.79.0