Skip to content
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

Type inference of integer literals is inconsistenct with the reference #104

Open
steveklabnik opened this issue Aug 30, 2017 · 3 comments
Open
Labels
A-types Area: Types C-bug Incorrect statements, terminology, or rendering issues

Comments

@steveklabnik
Copy link
Member

steveklabnik commented Aug 30, 2017

Originally at rust-lang/rust#41060

The reference currently says the following for integer literals

The type of an unsuffixed integer literal is determined by type inference:
[...]
If the program context under-constrains the type, it defaults to the signed 32-bit integer i32.

This does however not work for some inherent methods of signed integer types:

trait A {
    fn what_type(&self);
}


impl A for i16 {
    fn what_type(&self) {
        println!("i16");
    }
}

impl A for i32 {
    fn what_type(&self)  {
        println!("i32");
    }
}

fn main() {
    let z = 1;
    z.what_type();
    //z.is_positive(); // <- uncomment this line
}

As you can see, z is under-constrained in this case. The compiler does the right thing and defaults to type i32, so calling the trait method what_type() works.

If you uncomment the inherent method call to is_positive(), z still is under-constrained in pretty much the same way as before, however, the compiler fails to default to i32 and instead prints

error: no method named `is_positive` found for type `{integer}` in the current scope

Also note that the reference says

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

But the following example show that the order of statements is important:

fn one() { // compiles
    let a = 0;
    take_some(a);
    a.is_positive();
}

fn two() { // does not compile
    let a = 0;
    a.is_positive();
    take_some(a);
}

fn take_some(var: i32) {
    // do nothing
}

I think floating-point literals have the same issue, but I haven't checked.

rust-lang/rust#39255 and rust-lang/rust#40985 may be related.

@Havvy Havvy added the C-bug Incorrect statements, terminology, or rendering issues label Sep 23, 2017
@ehuss ehuss added the A-types Area: Types label Apr 21, 2019
@varkor
Copy link
Member

varkor commented Jan 14, 2020

We need to be more specific about what the following actually means:

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

As it's written, it's not strictly true. For instance, we have the following:

let _: u8 = 5 + 5; // ok
let _: u8 = &5 + 5; // not okay (allowed after #68129)
let _: u8 = 5 + &5; // not okay (allowed after #68129)
let _: u8 = &5 + &5; // not okay (allowed after #68129)
let _: u8 = &&5 + &&5; // not okay

It's not clear how these fit into the scheme mentioned in the reference, or, indeed, what the correct behaviour ought to be.

cc rust-lang/rust#68129

@Ruslanmsv
Copy link

Ruslanmsv commented Jul 2, 2022

Learning Rust i've tried to compile such piece of code

fn main() {
    let arr = vec![-1, 0, 2]; 
    let s  = arr.iter().filter(|x| x.is_positive()).sum();
    println!("{}", s);
}

and received this error
error[E0599]: no method named `is_positive` found for reference `&&{integer}` in the current scope

Explicit type annotation fixes the problem.

The only related info i've found was this issue. Is it a compiler bug, or a mistake in the reference?

@madsmtm
Copy link
Contributor

madsmtm commented Dec 2, 2023

I think it's considered a bug in rustc that type inference doesn't work properly on inherent methods, see rust-lang/rust#24124.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-types Area: Types C-bug Incorrect statements, terminology, or rendering issues
Projects
None yet
Development

No branches or pull requests

6 participants