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

Possible to mutably borrow elements inside a Vec inside a HashMap multiple times #17500

Closed
tedsta opened this issue Sep 24, 2014 · 8 comments · Fixed by #17517
Closed

Possible to mutably borrow elements inside a Vec inside a HashMap multiple times #17500

tedsta opened this issue Sep 24, 2014 · 8 comments · Fixed by #17517
Labels
A-lifetimes Area: Lifetimes / regions
Milestone

Comments

@tedsta
Copy link
Contributor

tedsta commented Sep 24, 2014

Sorry, I'm not sure how to describe this very well in a sentence. I am able to mutably borrow the innermost values of a HashMap<u32, Vec<int>>, delete the values, then reference them after they were deleted. This code compiles, runs, and barfs out strange numbers.

use std::collections::HashMap;

fn main() {
    let mut my_stuff: HashMap<u32, Vec<int>> = HashMap::new();
    my_stuff.insert(0, vec![1, 2, 3, 4]);

    // Do bad things
    let mut stuff = vec!();
    for (_, vec) in my_stuff.mut_iter() {
        for thing in vec.mut_iter() {
            stuff.push(thing);
        }
    }

    my_stuff.clear();

    for thing in stuff.iter() {
        println!("{}", *thing);
    }
}
@krdln
Copy link
Contributor

krdln commented Sep 24, 2014

Little bit shorter example, without mutable borrows. But still fails to freeze my_stuff:

fn main() {
    let mut my_stuff = std::collections::HashMap::new();
    my_stuff.insert(0i, 42i);

    let (_, thing) = my_stuff.iter().next().unwrap();

    my_stuff.clear();

    println!("{}", *thing);
}

@pcwalton
Copy link
Contributor

nominating for 1.0 P-backcompat-lang

@pcwalton
Copy link
Contributor

though this may be a library issue

@thestinger thestinger added the A-lifetimes Area: Lifetimes / regions label Sep 24, 2014
@Gankra
Copy link
Contributor

Gankra commented Sep 24, 2014

0.o weird

This code is also valid:

    let mut my_stuff = std::collections::HashMap::new();
    my_stuff.insert(0i, 42i);

    let mut it = my_stuff.iter();
    my_stuff.swap(1, 43);

This is because the hashmap iterator just wraps the rawtable iterator, which just defers to the RawBuckets iterator, which is just a wrapper around two *mut's. That is, literally none of these iterators actually borrows the hashmap. Presumably this is fixable by taking a useless reference somewhere.

The other thing I'm seeing is that there's struct Entries<'a, K, V>, but the signature for Hashmap's iterator function is pub fn iter(&self) -> Entries<K, V>. How is this lifetime being elided? Is it doing the same thing as fn get(&self) -> &T, or is something else happening?

CC @pczarn

@Gankra
Copy link
Contributor

Gankra commented Sep 24, 2014

Yep, it's eliding 'static!

fn main() {
    let mut my_stuff = std::collections::HashMap::new();

    // ok
    let foo: Entries<'static, int, int> = my_stuff.iter();

    // error: borrowed value does not live long enough
    // let bar: Items<'static, int> = vec!(1i).iter();
}

@Gankra
Copy link
Contributor

Gankra commented Sep 24, 2014

So there's two bugs here: the iterator doesn't borrow the map, and the references are being yielded as 'static.

@pnkfelix
Copy link
Member

Assigning P-backcompat-libs, 1.0

@Gankra
Copy link
Contributor

Gankra commented Sep 27, 2014

@pczarn thanks for fixing this! Great job!

lnicola pushed a commit to lnicola/rust that referenced this issue Jul 11, 2024
fix: completions after async kw

fix rust-lang#17500

### Changes

1. fix completions after async kw
2. fix completions for `async` kw in trait
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lifetimes Area: Lifetimes / regions
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants