Skip to content

rustc fails to infer types, provides confusing error message #37528

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
jimblandy opened this issue Nov 2, 2016 · 7 comments
Closed

rustc fails to infer types, provides confusing error message #37528

jimblandy opened this issue Nov 2, 2016 · 7 comments

Comments

@jimblandy
Copy link
Contributor

jimblandy commented Nov 2, 2016

Rust is unable to infer the element type in the results of a call to Iterator::partition if the item type is a reference, but not if it's an integer. The error message says nothing about lifetimes, or any other characteristic specific to references.

In nightly Rust, compiling the following code:

fn main() {
    let one = Some(1i32);

    // Rust won't infer the element type here:
    let _a: (Vec<_>, Vec<_>) = one.iter().partition(|_v| true);
    
    // But it does here:
    let _a: (Vec<_>, Vec<_>) = one.iter().cloned().partition(|_v| true);
    
    // And it infers Vec<i32> here:
    let _a: (Vec<_>, Vec<_>) = (0i32..1).partition(|_v| true);    
}

produces the following error:

error[E0282]: unable to infer enough type information about `_`
 --> <anon>:3:13
  |
3 |     let _a: (Vec<_>, Vec<_>) = Some(1i32).iter().partition(|_v| true);
  |             ^^^^^^^^^^^^^^^^ cannot infer type for `_`
  |
  = note: type annotations or generic parameter binding required

It's not clear to me at all why making the iterator clone the items, or using an iterator that doesn't produce references in the first place, should make the type inference work; it seems like partition should be as happy to build a vector of references as a vector of integers.

This is using: rustc 1.14.0-nightly (3f4408347 2016-10-27)

@sinkuu
Copy link
Contributor

sinkuu commented Nov 2, 2016

Iterator::partition's results type requires Extend. Extend is implemented for:

impl<T> Extend<T> for Vec<T>
impl<'a, T> Extend<&'a T> for Vec<T> where T: Copy + 'a

etc, so you can type it in two ways, resulting in inference error:

let _a: (Vec<&i32>, Vec<&i32>) = one.iter().partition(|_v| true);
let _a: (Vec<i32>, Vec<i32>) = one.iter().partition(|_v| true);

It's not clear to me at all why making the iterator clone the items, or using an iterator that doesn't produce references in the first place,

You can use into_iter.

@jimblandy
Copy link
Contributor Author

Thank you very much for the explanation. How did you find those two implementations?

@sinkuu
Copy link
Contributor

sinkuu commented Nov 2, 2016

You can find them in https://doc.rust-lang.org/std/iter/trait.Extend.html .

@jimblandy
Copy link
Contributor Author

jimblandy commented Nov 2, 2016

I meant, how did you figure out that those two implementations were the cause of the problem? I'd like to be able to sort out problems like this without asking for help in the future.

@sinkuu
Copy link
Contributor

sinkuu commented Nov 3, 2016

fn partition<B, F>(self, f: F) -> (B, B) where B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool

Looking at Iterator::partition's where clause, I wondered why Extend<Self::Item> doesn't determine Vec<_> as Vec<Self::Item>. Then I found Extend<&T> is implemented for both Vec<T> and Vec<&T> if T: Copy.

@StefanoChiodino
Copy link

StefanoChiodino commented Oct 24, 2017

Took me a while to figure out what Rust meant by B! I guess being more familiar with c# it would have been easier for me if it was called T2 or something.

It's not always easy to navigate around and found the B, would it not be nice to have the signature spit out in the error so that you can read it straight away?

This is my case https://play.rust-lang.org/?gist=9a32f20e9c272e256f93ca772b1f527e&version=stable

@kennytm
Copy link
Member

kennytm commented Oct 24, 2017

@StefanoChiodino That would be issue #45164.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants