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

partially initialized structs in local variables, similar to partially moved structs, perhaps should be possible #448

Open
comex opened this issue Nov 6, 2014 · 8 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@comex
Copy link

comex commented Nov 6, 2014

Here are two examples where currently a dummy value for a struct field is needed, but the compiler could allow it to be safely left uninitialized by noticing that it's always initialized before being used externally. This is quite analogous to partially moved structs, where the compiler currently allows moving out fields as long as you put them back before using the struct externally (even if the latter is in a loop, as in the second example); but in this case the struct would start in a "partially moved" state.

Even though I think this is a fairly unusual use case (at least, as long as it doesn't allow calling methods in the partially uninitialized state), the added semantic complexity is pretty minimal, so I think it's worth considering.

use std::cell::RefCell;
struct Foo<'a> {
    a: RefCell<int>,
    b: &'a RefCell<int>,
}
struct Bar {
    a: int,
    // assume some other stuff
}
fn main() {
    // Case 1: assigning a reference to point to the struct itself (somewhat
    // limited since the struct can't be moved, but potentially useful)
    let mut foo = Foo {
        a: RefCell::new(1),
        b: /* dummy */ &RefCell::new(1),
    };
    foo.b = &foo.a;

    // Case 2: assigning inside a loop
    let mut bar = Bar {
        /* dummy */ a: 0,
    };
    for &a in [1, 2, 7].iter() {
        bar.a = a;
        // call some method on bar
    }
}
@Gankra
Copy link
Contributor

Gankra commented Nov 6, 2014

What happens if I panic between making the struct and fully initializing it?

@comex
Copy link
Author

comex commented Nov 6, 2014

The same thing as in the partially moved case.

@reem
Copy link

reem commented Nov 6, 2014

Also, the above example won't work anyway, since you could move foo.a while foo.b still exists.

@comex
Copy link
Author

comex commented Nov 6, 2014

If I simulate an uninitialized state by turning b into b: RefCell<&'a RefCell<int>> (just to make it non-Copy; nothing important about the outer RefCell), and partially moving b immediately after creating the struct, the compiler is okay with it. After filling in foo.b again, I can call &self methods on the object and whatnot. So I think it should work...

@pcwalton
Copy link
Contributor

I believe @comex is correct and there is nothing semantically wrong with this.

@petrochenkov petrochenkov added the T-lang Relevant to the language team, which will review and decide on the RFC. label Jan 19, 2018
@crlf0710
Copy link
Member

Now we have MaybeUninit, which covers these use cases. Maybe this can be closed now. @Centril

@CryZe
Copy link

CryZe commented Oct 29, 2019

OP is about doing so safely, while MaybeUninit is doing so unsafely. MaybeUninit certainly works, but having the language recognize that the use cases shown are safe would be much better.

@shepmaster
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

8 participants