Skip to content

segfault in repr with references #3501

Closed

Description

@erickt
struct A {
    x: ~int,
    mut y: ~[&~int],
}

fn A() -> A {
    let a = A { x: ~1, y: ~[] };
    vec::push(a.y, &a.x);
    a
}

fn main() {
    let a = A();
    error!("%?", a);
}

Results in a secgault. The stack trace suggests it's in the repr function:

0x000000010007309d in repr::__extensions__::meth_10746::visit_self_describing_heap_alloc::_b764c3ece7f574bd::_04 ()
(gdb) bt
#0  0x000000010007309d in repr::__extensions__::meth_10746::visit_self_describing_heap_alloc::_b764c3ece7f574bd::_04 ()
#1  0x0000000000000000 in ?? ()

Activity

  1. nikomatsakis commented on Sep 15, 2012

    @nikomatsakis
    Contributor

    This definitely should not type check. You are returning a pointer into the stack frame.

  2. nikomatsakis commented on Sep 15, 2012

    @nikomatsakis
    Contributor

    I added this to 0.4 milestone and assigned myself. I think it's pretty important to get this right. I'm having a hard time debugging it, though, due to #3506

  3. nikomatsakis commented on Sep 17, 2012

    @nikomatsakis
    Contributor

    Actually, this is due to the unsound type of vec::push()! It's worse than I thought. If you change the example to:

    struct A {
        x: ~int,
        mut y: ~[&~int],
    }
    
    fn push<T>(v: &mut ~[T], +x: T) {
        vec::push(*v, move x);
    }
    
    fn A() -> A {
        let a = A { x: ~1, y: ~[] };
        push(&mut a.y, &a.x);
        a
    }
    
    fn main() {
        let a = A();
        error!("%?", a);
    }
    

    then you get the region error I expected:

    Running /usr/local/bin/rustc:
    /Users/nmatsakis/tmp/bug3501.rs:12:20: 12:21 error: illegal borrow: borrowed value does not live long enough
    /Users/nmatsakis/tmp/bug3501.rs:12     push(&mut a.y, &a.x);
                                                           ^
    /Users/nmatsakis/tmp/bug3501.rs:10:12: 14:1 note: borrowed pointer must be valid for the anonymous lifetime #1 defined on the block at 10:12...
    /Users/nmatsakis/tmp/bug3501.rs:10 fn A() -> A {
    /Users/nmatsakis/tmp/bug3501.rs:11     let a = A { x: ~1, y: ~[] };
    /Users/nmatsakis/tmp/bug3501.rs:12     push(&mut a.y, &a.x);
    /Users/nmatsakis/tmp/bug3501.rs:13     a
    /Users/nmatsakis/tmp/bug3501.rs:14 }
    /Users/nmatsakis/tmp/bug3501.rs:10:12: 14:1 note: ...but borrowed value is only valid for the block at 10:12
    /Users/nmatsakis/tmp/bug3501.rs:10 fn A() -> A {
    /Users/nmatsakis/tmp/bug3501.rs:11     let a = A { x: ~1, y: ~[] };
    /Users/nmatsakis/tmp/bug3501.rs:12     push(&mut a.y, &a.x);
    /Users/nmatsakis/tmp/bug3501.rs:13     a
    /Users/nmatsakis/tmp/bug3501.rs:14 }
    error: aborting due to previous error
    
  4. graydon commented on Sep 18, 2012

    @graydon
    Contributor

    Dupe of #3513, closing.

  5. nikomatsakis commented on Sep 18, 2012

    @nikomatsakis
    Contributor

    Closing as dup of #3513.

  6. added a commit that references this issue on Apr 25, 2024
  7. added 2 commits that reference this issue on Aug 21, 2026
    3e85997
    5da2905
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions