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

Should there be a compiler error here? #226

Closed
LucasSte opened this issue May 10, 2022 · 3 comments
Closed

Should there be a compiler error here? #226

LucasSte opened this issue May 10, 2022 · 3 comments
Labels

Comments

@LucasSte
Copy link

LucasSte commented May 10, 2022

I created the following example code:

use indexmap::IndexMap;

struct SaveSmth {
    pub a: usize,
}
fn main() {
    let mut imp : IndexMap<usize, SaveSmth> = IndexMap::new();
    imp.insert(8, SaveSmth{a : 3});

    let mut vec : Vec<(usize, usize)> = Vec::new();

    vec.push((8, 1));

    for item in vec {
        let a = &imp[item.0];
        println!("{}", a.a);
    }
}

Rust panics in let a = &imp[item.0] and the correct way to fetch the value should be let a = &imp[&item.0];. Shouldn't there be a compiler error because I'm passing the wrong type to look up the table?

The panic message says "index out of bounds":

thread 'main' panicked at 'IndexMap: index out of bounds', src/main.rs:16:18
@cuviper
Copy link
Member

cuviper commented May 10, 2022

It's not an error, but I can see why you're surprised -- I even mentioned this possible confusion in #132.

There are two flavors of indexing here: Index<&Q> for map-like key lookup (with Q: Equivalent<K>), and Index<usize> for vector-like indexing, which is the sort of capability that gives us "index" in the crate and type names. #177 also added indexing with usize ranges to get a Slice, but this is not published yet.

So when your K is also usize, there is an unfortunate footgun that map[i] and map[&i] are both valid, as far as the compiler is concerned, but only you know which is actually appropriate for that i: usize.

@LucasSte
Copy link
Author

LucasSte commented May 13, 2022

I did not understand what indexing with usize is supposed to return. In my example, if I indexed the map without an ampersand imp[item.0], what should that retrieve?

@cuviper
Copy link
Member

cuviper commented May 13, 2022

Index<&Q> is by key, like a HashMap, so imp[&item.0] returns the entry with that given key.

Index<usize> is by position, like Vec, so imp[0] is the first, imp[1] is the second, etc., in the same order you get from the iterators. IndexMap preserves the insertion order, unless you alter that with methods like swap or remove. For your example that has item.0 == 8, imp[8] is out of bounds because there is only one item in the map -- only imp[0] is in bounds.

@cuviper cuviper closed this as completed Jun 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants