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

Memory unsafety using & bindings more than one level deep when destructuring #19997

Closed
pythonesque opened this issue Dec 18, 2014 · 5 comments
Closed
Assignees

Comments

@pythonesque
Copy link
Contributor

This segfaults.

// Note: you can also replicate this with this function signature.
// fn foo<'a, 'b, 'c>(mut pair: (&'c mut &'a mut Vec<Option<String>>, &'b mut Vec<&'a mut Option<String>>)) {
//     let mut pair = (&mut a, &mut b);
// }

fn main() {
    let mut a = Vec::new();
    let mut a = &mut a;
    let mut b = Vec::new();
    for _ in range(0u8, 9) {
        //foo((&mut a, &mut b));
        // Correctly complains if you do: let (ref mut a, ref mut b) = (&mut a, &mut b);
        // Also correctly complains in Rust 0.12.
        let (&ref mut a, ref mut b) = (&mut a, &mut b);
        a.push(Some("".to_string()));
        let index = a.len() - 1;
        let data = a.as_mut_slice().get_mut(index).unwrap();
        b.push(data);
    }
    println!("{}", b);
}
@nikomatsakis
Copy link
Contributor

cc me

@nikomatsakis
Copy link
Contributor

Nominating.

@pythonesque
Copy link
Contributor Author

Simplified test case (no unsafe code):

fn main() {
    let a = 0u8;
    let mut a = Some(&a);
    if let (&Some(ref b),) = (&a,) {
        a = None;
        println!("{}, {}", a, b);
    }
}

This seems to be an issue with tuple patterns specifically. I can't get it to happen if I try the same thing without one. The behavior suggests to me that borrowck does not consider &a to borrow a in such patterns.

@pythonesque pythonesque changed the title Memory unsafety with &ref mut bindings Memory unsafety using tuple patterns with & bindings Dec 19, 2014
@pythonesque
Copy link
Contributor Author

Actually, I can make it happen for tuple structs as well:

fn main() {
    struct Foo<'a, 'b: 'a>(&'a Option<&'b u8>);
    let a = 0u8;
    let mut a = Some(&a);
    if let Foo(&Some(ref b)) = Foo(&a) {
        a = None;
        println!("{}, {}", a, b);
    }
}

and regular structs:

fn main() {
    struct Foo<'a, 'b: 'a> { data: &'a Option<&'b u8> };
    let a = 0u8;
    let mut a = Some(&a);
    if let Foo { data: &Some(ref b) } = (Foo { data: &a }) {
        a = None;
        println!("{}, {}", a, b);
    }
}

and even enum variants:

fn main() {
    struct Foo<'a, 'b: 'a>(&'a Option<&'b u8>);
    let a = 0u8;
    let mut a = Some(&a);
    if let Foo::Foo(&Some(ref b)) = Foo::Foo(&a) {
        a = None;
        println!("{}, {}", a, b);
    }
}

@pythonesque pythonesque changed the title Memory unsafety using tuple patterns with & bindings Memory unsafety using & bindings more than one level deep when destructuring Dec 19, 2014
@nikomatsakis nikomatsakis self-assigned this Jan 4, 2015
@nikomatsakis
Copy link
Contributor

Got a fix coming.

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

2 participants