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

uninitialized/zeroed statics/consts #411

Closed
Zoxc opened this issue Oct 24, 2014 · 18 comments
Closed

uninitialized/zeroed statics/consts #411

Zoxc opened this issue Oct 24, 2014 · 18 comments
Labels
T-compiler Relevant to the compiler team, which will review and decide on the RFC. T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@Zoxc
Copy link

Zoxc commented Oct 24, 2014

There should be a way to create consts, statics and static muts which are partially or fully uninitialized or zeroed.

One way to do this could be to create built-in unsafe generic constants ZEROED and UNDEF.

@eddyb suggested to make the existing intrinsics usable in statics

A crude solution could be to allow the initializer in a static mut to be left out, which should cause zeroing all it's memory.

@arielb1
Copy link
Contributor

arielb1 commented Oct 24, 2014

All-bits-zero isn't special in Rust (up to dynamic drops, which are being removed). Allowing some kind of mem::uninitialized() would be nice, through.

@mahkoh
Copy link
Contributor

mahkoh commented Oct 24, 2014

Sounds like CTFE. See #322 for another proposal that suggested limited CTFE for intrinsic functions.

@arielb1
Copy link
Contributor

arielb1 commented Oct 24, 2014

@mahkoh

We do have a limited version of CTFE. Currently it is limited to arithmetic and constructors. mem::uninitialized() won't increase its complexity so much .

However, adding size_of would complicate things more, because constants can be a part of type-checking, and this would make type-checking depend on LLVM. Because recursion in structs is so limited, this would still be tractable, but if we add traits etc. it would be a major mess.

I'm talking about stuff like:

trait Tr { fn doit(&self); }
impl Tr for [uint, ..std::mem::size_of::<uint>()] {
    fn doit(&self) { println!("called uint"); }
}
impl Tr for [uint, ..12-std::mem::size_of::<uint>()] {
    fn doit(&self) { println!("called 12-uint"); }
}

fn main() {
    let s = [0,1,2,3u];
    s.doit(); // which .doit is called depends on architecture
}

We could get around this by treating such values as "abstract values", so that they don't interfere with type-checking, and only expand them in trans. Of course this would create 2 kinds of constexprs, but otherwise we would be getting into what seems to me like a pretty deep dependent type hole.

C gets away with this because it "executes" declarations one-by-one.

@eddyb
Copy link
Member

eddyb commented Oct 25, 2014

@arielb1 you can already do that, using uint::BYTES or uint::BITS.

@arielb1
Copy link
Contributor

arielb1 commented Oct 25, 2014

uint was just a simple example, whose size is a well-known constant – you could put more complicated types there so we need to put trans::adt-s size calculation code into rustc.

@eddyb
Copy link
Member

eddyb commented Oct 25, 2014

AFAIK, the size calculations are done by LLVM. We could have a LLVM context during type-checking, is there anything problematic with that? We should do that anyway instead of the hacks we've thrown around transmute.

@arielb1
Copy link
Contributor

arielb1 commented Oct 25, 2014

@eddyb

They are done via LLVM and a big part of trans. I'll prefer keeping them separate. Actually, if we allow calling trait methods in constexprs then we'll have a total dependent type mess, and I strongly prefer not to go there, so we need to stop somewhere.

@arielb1
Copy link
Contributor

arielb1 commented Oct 25, 2014

There is also the problem of struct -> constexpr recursion. Because there are only finitely many constants we can handle this with a DFS, but if we allow functions this could get more complicated.

@eddyb
Copy link
Member

eddyb commented Oct 25, 2014

A big part of trans? I find it's quite isolated, compared to anything which deals with Block, for example.

if we allow calling trait methods in constexprs

Nobody said anything about that. You couldn't even use a size_of intrinsic or associated constant, with a non-concrete type parameter, as the length of an array (e.g. impl<T> Cast<T> for [u8, ..size_of::<T>()]) because the length has to be constant before monomorphization, though that may change at some point.

@petrochenkov petrochenkov added T-lang Relevant to the language team, which will review and decide on the RFC. T-compiler Relevant to the compiler team, which will review and decide on the RFC. labels Jan 19, 2018
@gnzlbg
Copy link
Contributor

gnzlbg commented Feb 22, 2018

Would it be possible to make mem::uninitialized a const fn ? (or mem::zeroed?)

@oli-obk
Copy link
Contributor

oli-obk commented Feb 22, 2018

@gnzlbg once rust-lang/rust#46882 is merged, that is a trivial addition! (imo even uncontroversial, since you can write an unsafe const fn yourself that does the same thing via unions).

union Foo<T> {
    t: T,
    u: (),
}
unsafe const fn uninitialized<T>() -> T {
    Foo { u: () }.t
}

@gnzlbg
Copy link
Contributor

gnzlbg commented Mar 27, 2018

@oli-obk congrats on the merge of that PR :)

Any news about this? This issue comes up every now and then in stdsimd: rust-lang/stdarch#403 (comment)

@oli-obk
Copy link
Contributor

oli-obk commented Mar 27, 2018

My feeling is that someone should just open a PR and we FCP it, because you can do zeroed/uninitialized with horrible hacks in constants, so why not allow the nice obvious ways, too!?

Implementation guide: grep for "size_of" (yes with quotes) in rustc, grep for "uninitialized" in the miri repository, copy over code from the miri repository to rustc.

@richard-uk1
Copy link

@oli-obk can you give some more hints? I can't find any code for "uninitialized" in miri that looks like the const eval stuff in librustc_mir/interpret/const_eval. Also, would I need to add uninitialized/zeroed to the intrinsics?

@oli-obk
Copy link
Contributor

oli-obk commented Jun 10, 2018

So... I've been told that these intrinsics should not exist due to various unsafety rules not playing nice with them.

Instead of creating a static/const with one of these intrinsics, your static/const should be of Union type with a zst variant that you use to "initialize" it.

I'm not sure this issue can be acted on. Maybe we should close it?

cc @RalfJung

@RalfJung
Copy link
Member

Seems like essentially a duplicate of rust-lang/rust#50150 to me.

Instead, we should strive to stabilize MaybeUninit and make it usable from const context.

@richard-uk1
Copy link

I've now read the other issue & the MaybeUninit RFC and it does seem like this is a duplicate of the other issue. Maybe close this so no-one tries to implement it?

@Centril
Copy link
Contributor

Centril commented Nov 27, 2018

Closing as ~"completed".

@Centril Centril closed this as completed Nov 27, 2018
wycats pushed a commit to wycats/rust-rfcs that referenced this issue Mar 5, 2019
Add Ember.js PR link for emberjs#337
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-compiler Relevant to the compiler team, which will review and decide on the RFC. T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

10 participants