Skip to content

Confusing type-deduction of integer literals in generic contexts #39255

Closed
@gnzlbg

Description

@gnzlbg

The way in which the types of integer literals are deduced in generic contexts is confusing. For example, the following:

trait Int {}
impl Int for i16 {}
impl Int for i32 {}
trait UInt {}
impl UInt for u16 {}
impl UInt for u32 {}

fn foo<T: Int>(x: T) { println!("size: {}", std::mem::size_of::<T>()); }
fn bar<T: UInt>(x: T) { println!("size: {}", std::mem::size_of::<T>()); }

fn main() {
  foo(10);
  bar(10);
}

works for foo but fails for bar. Weirder is that uncommenting the impl UInt for u16 {} makes it work.

IMO both cases should either work or fail (I would prefer work).

The error messages is:

error[E0277]: the trait bound `i32: UInt` is not satisfied
  --> <anon>:13:3
   |
13 |   bar(10);
   |   ^^^ the trait `UInt` is not implemented for `i32`
   |
   = note: required by `bar`

error: aborting due to previous error

I interpret from this that rustc is only trying with i32 (for whatever reason) even though the code does not contain any explicit mention of i32 anywhere. Still, removing one of the impls of UInt makes the program type-check, so rustc is able to deduce unsigned integer types in some situations.

EDIT: After going through the book without any luck, I found the following in the Rust language reference:

The type of an unsuffixed integer literal is determined by type inference:

- 1. If an integer type can be uniquely determined from the surrounding program context, the unsuffixed integer literal has that type.

- 2. If the program context under-constrains the type, it defaults to the signed 32-bit integer i32.

- 3. If the program context over-constrains the type, it is considered a static type error.

I guess that removing the impl UInt for u16 {} switches from rule 2 to rule 1, explaining the behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceC-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-langRelevant to the language team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions