rust-lang / rust-lang/rust

Integer literal type inference causes weird behavior including strange compiler diagnostic (but the suggestion is working).

Open
#129,360 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics A-inference C-discussion T-compiler T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
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
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):

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):

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
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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the minimal Rust program with rustc 1.80.1, then compare it with the versions that add a type annotation or an explicit integer type. The issue is done when the unannotated let y = stuff * 2 case compiles without the E0282 diagnostic.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.