Skip to content

Confusing type inference around integer literals #71791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
XAMPPRocky opened this issue May 2, 2020 · 1 comment
Closed

Confusing type inference around integer literals #71791

XAMPPRocky opened this issue May 2, 2020 · 1 comment
Labels
A-inference Area: Type inference C-bug Category: This is a bug.

Comments

@XAMPPRocky
Copy link
Member

This might be a duplicate of #39255, I'm not sure. But it's not clear why the type is correctly inferred for u8 but isn't for u32.

I tried this code:

#[derive(Default)]
pub struct Builder {
    per_page: Option<u8>,
    page: Option<u32>,
}

impl Builder {
    pub fn per_page(mut self, per_page: impl Into<u8>) -> Self {
        self.per_page = Some(per_page.into());
        self
    }

    pub fn page(mut self, page: impl Into<u32>) -> Self {
        self.page = Some(page.into());
        self
    }
}

fn main() {
    let builder = Builder::default()
        .per_page(25)
        // Doesn't work
        .page(25);
        // Works
        .page(25u32);
}

I expected to see this happen: This code compiles successfully.

Instead, this happened:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `u32: std::convert::From<i32>` is not satisfied
  --> src/main.rs:24:51
   |
24 |     let builder = Builder::default().per_page(25).page(25);
   |                                                   ^^^^ the trait `std::convert::From<i32>` is not implemented for `u32`
   |
   = help: the following implementations were found:
             <u32 as std::convert::From<bool>>
             <u32 as std::convert::From<char>>
             <u32 as std::convert::From<std::net::Ipv4Addr>>
             <u32 as std::convert::From<std::num::NonZeroU32>>
           and 2 others
   = note: required because of the requirements on the impl of `std::convert::Into<u32>` for `i32`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground`.

To learn more, run the command again with —verbose.

Meta

rustc --version --verbose:

rustc 1.43.0 (4fb7144ed 2020-04-20)
binary: rustc
commit-hash: 4fb7144ed159f94491249e86d5bbd033b5d60550
commit-date: 2020-04-20
host: x86_64-apple-darwin
release: 1.43.0
LLVM version: 9.0
@XAMPPRocky XAMPPRocky added C-bug Category: This is a bug. A-inference Area: Type inference labels May 2, 2020
@jonas-schievink
Copy link
Contributor

This is because there is only one impl Into<u8> for X that applies when X is an integer type variable, which is the blanket From impl, which then calls the reflective impl<T> From<T> for T impl, so the compiler knows that the type has to be u8.

u32 has impls of From<u16> and From<u8>, in addition to the reflective From<u32> impl, so the compiler doesn't know which integer type to use.

It's different from #39255 since this issue doesn't rely on the i32 fallback, instead running into multiple applicable impls, but I believe both are expected behavior, so closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inference Area: Type inference C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

2 participants