Skip to content

cannot infer type when expression is logically negated in closure #106138

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

Open
Isopod opened this issue Dec 25, 2022 · 4 comments
Open

cannot infer type when expression is logically negated in closure #106138

Isopod opened this issue Dec 25, 2022 · 4 comments
Labels
A-closures Area: Closures (`|…| { … }`) A-inference Area: Type inference C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Isopod
Copy link

Isopod commented Dec 25, 2022

Hi! I’m pretty new to Rust, but I think I just encountered a bug in the compiler.

For some reason, Rust cannot “infer” the type of !a[i] in this code:

pub fn myfunction(x: &Vec<bool>) {
    let closure = |i, a: &Vec<bool>| { !a[i] };
    closure(0, x);
}
error[E0282]: type annotations needed
 --> main.rs:2:40
  |
2 |     let closure = |i, a: &Vec<bool>| { !a[i] };
  |                                        ^^^^^ cannot infer type

error: aborting due to previous error

For more information about this error, try `rustc --explain E0282`.

But when you replace !a[i] with just a[i], then it compiles without error. So the error only occurs when there is a logical negation.

While narrowing this down, I also noticed that the error message appears to be a bit misleading: It looks like the compiler actually fails to infer the type of i, not !a[i], as the error goes away when I add a type annotation for i. Here is a more elaborate example, combining all of my three test cases:

pub fn myfunction(x: &Vec<bool>) {
    let one = |i, a: &Vec<bool>| {
        a[i]  // ok
    };
    let two = |i, a: &Vec<bool>| {
        !a[i] // cannot infer type
    };
    let three = |i: usize, a: &Vec<bool>| {
        !a[i] // ok
    };

    one(0, x);
    two(0, x);
    three(0, x);
}

fn main() {
}

Run it on Rust Playground

Reproduces on Stable, Beta and Nightly.

@Isopod Isopod added the C-bug Category: This is a bug. label Dec 25, 2022
@chenyukang
Copy link
Member

@rustbot claim

@chenyukang
Copy link
Member

emm, this is because if i is without type, then a[i] will be a infer(_),
the closure one is return type is also _, so there is no error,
but ! with type _ is an error.
Need more dig for potential fix.

@Isopod
Copy link
Author

Isopod commented Jan 23, 2023

It appears to happen with other unary operators as well, but never with binary operators:

pub fn bools(x: &Vec<bool>) {
    let binary = |i, a: &Vec<bool>| {
        a[i] && a[i+1] // ok
    };

    let unary = |i, a: &Vec<bool>| {
        !a[i] // cannot infer type
    };

    binary(0, x);
    unary(0, x);
}

pub fn ints(x: &Vec<isize>) {
    let binary = |i, a: &Vec<isize>| {
        a[i] + a[i+1] // ok
    };
    let unary = |i, a: &Vec<isize>| {
        -a[i] // cannot infer type
    };
    
    binary(0, x);
    unary(0, x);
}
Compiling playground v0.0.1 (/playground)
error[[E0282]](https://doc.rust-lang.org/stable/error-index.html#E0282): type annotations needed
 --> src/main.rs:7:9
  |
7 |         !a[i] // cannot infer type
  |         ^^^^^ cannot infer type

error[[E0282]](https://doc.rust-lang.org/stable/error-index.html#E0282): type annotations needed
  --> src/main.rs:20:9
   |
20 |         -a[i] // cannot infer type
   |         ^^^^^ cannot infer type

For more information about this error, try `rustc --explain E0282`.
error: could not compile `playground` due to 2 previous errors

Playground

@chenyukang
Copy link
Member

I can not figure out a proper fix for this issue right now.
release for anyone want to have a try.
My branch FYI #107567

@chenyukang chenyukang removed their assignment Feb 25, 2023
@fmease fmease added A-closures Area: Closures (`|…| { … }`) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-inference Area: Type inference and removed needs-triage-legacy labels Jan 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-closures Area: Closures (`|…| { … }`) A-inference Area: Type inference C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants