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 depends on ordering #42333

Closed
mulkieran opened this issue May 31, 2017 · 4 comments
Closed

Type inference depends on ordering #42333

mulkieran opened this issue May 31, 2017 · 4 comments

Comments

@mulkieran
Copy link

This code ( https://is.gd/6jsqIt) gives the following compile error:

use std::path::PathBuf;

pub struct Thing {
    pub f1: PathBuf,
}

fn junk() -> Vec<Thing> {

    let mut things = Vec::new();
    for x in vec![1, 2, 3] {
        if x == 2 {
            for thing in things.drain(..) {
                thing.f1.clone();
            }
            return vec![]
        }
        things.push(Thing{f1: PathBuf::from(format!("/{}", x))});
    }   
    things  
}               
            
fn main() { 
    junk();
}
rustc 1.17.0 (56124baa9 2017-04-24)
error: the type of this value must be known in this context
  --> <anon>:13:17
   |
13 |                 thing.f1.clone();
   |                 ^^^^^^^^

error: aborting due to previous error

I believe that the type of the error should be known in the context, because the type of things is certainly known, and therefore the types of the elements yielded by things.drain(). Note that the error has to do with the publicly accessible f1 field of thing, which should be know to be PathBuf.

I can eliminate the error by adding a type annotation of Vec<Thing> to the declaration of things.

I can also eliminate the error by swapping the positions of the things.push line and the if x == 2 block.

These facts are true as of today for Stable, Beta, Nightly.

@eddyb
Copy link
Member

eddyb commented Jun 7, 2017

This is a known limitation of the in-order type-checker. While inference flows freely, thing.f1.clone() is checked before things.push(Thing {...}) so it isn't known that thing: Thing when you try to access the f1 field. We may in the future move away from this, but there are no immediate plans.

@mulkieran
Copy link
Author

Thanks for the answer, which alas I do not fully understand. I took a look at the community resources, and there's a lot about a lot of subjects, but not much about how to intuit how the type-checker would be expected to behave. But I appreciate you letting me know that it is well understood and expected behaviour.

@eddyb
Copy link
Member

eddyb commented Jun 7, 2017

@mulkieran What I mean is that the type-checker goes through the function in the order it was written. It knows things is a Vec, but the element type isn't known until you push to it.

Fields accesses and methods calls are simply not supported unless the type is already known.

The information can come in various ways, even e.g. Vec::<Thing>::drain(&mut things), but it has to be present by the time you access a field or call a method (there's a few more cases like this).

@Mark-Simulacrum
Copy link
Member

Closing as a known limitation, that there's little point in tracking in separate issues.

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

3 participants