# Pre-RFC solidifying repr(Rust)

**URL:** <https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306>\
**Category:** Uncategorized\
**Created:** [June 29, 2015, 8:15am UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306 "2015-06-29T08:15:37Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gankra](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gankra/32/6002_2.png) [@Gankra](https://internals.rust-lang.org/u/Gankra)\
**Post date:** [June 29, 2015, 8:15am UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/1 "2015-06-29T08:15:37Z")

</div>

> <https://github.com/Gankro/rfcs/blob/repr-2/text/0000-solidify-default-repr.md>

---

<div class="post-metadata">

**Author:** ![llogiq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/llogiq/32/13692_2.png) [@llogiq](https://internals.rust-lang.org/u/llogiq)\
**Post date:** [June 29, 2015, 9:21am UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/2 "2015-06-29T09:21:38Z")

</div>

‘astrategy’ should probably read ‘strategy’.

Apart from that, I don’t understand why this is a breaking change. Could you add an example of code that breaks?

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [June 29, 2015, 9:49am UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/3 "2015-06-29T09:49:15Z")

</div>

I think a `repr(C)` struct with an unsized field being disallowed now is the only breaking change. So code fails to compile only because of a lint, not because something actually changed.

---

<div class="post-metadata">

**Author:** ![llogiq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/llogiq/32/13692_2.png) [@llogiq](https://internals.rust-lang.org/u/llogiq)\
**Post date:** [June 29, 2015, 10:31am UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/4 "2015-06-29T10:31:05Z")

</div>

I see, though I’m a bit surprised it is allowed now – surely code generation for such a struct must fail currently?

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [June 29, 2015, 1:25pm UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/5 "2015-06-29T13:25:13Z")

</div>

> Rust will use all of the same alignment and padding rules as repr(C), the only difference between repr(C) and repr(Rust) is the ordering of fields.

I'd refrain from giving this guarantee, C ABIs contain some weird cases, like different alignment of `double`s inside and outside of `struct`s on x86 Linux. I'm not sure Rust should necessarily repeat them.

```rust
#include <iostream>

struct S {
  int i;
  double d;
};

int main() {
  std::cout << sizeof(double) << ' ' << sizeof(S) << '\n';
  std::cout << alignof(double) << ' ' << alignof(S) << '\n';
}

we@we-kubuntu32:~$ ./a.out 
8 12
8 4

```

---

<div class="post-metadata">

**Author:** ![Gankra](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gankra/32/6002_2.png) [@Gankra](https://internals.rust-lang.org/u/Gankra)\
**Post date:** [June 29, 2015, 10:11pm UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/6 "2015-06-29T22:11:30Z")

</div>

> different alignment of doubles inside and outside of structs on x86 Linu

While that is indeed surprising, does it actually cause any trouble in practice?

Note that we need to _support_ such nonsense for `repr(C)` to actually work. The more we try to differ from C, the more we need to maintain.

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [June 29, 2015, 10:48pm UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/7 "2015-06-29T22:48:09Z")

</div>

I’m not talking about implementing/maintaining now, just about being cautious and not guaranteeing equivalency of `repr(Rust)` and `repr(C)` with regard to padding and alignment until the full story with Rust ABI is clear. For example, if we want the struct layout to be the same on Linux and Windows, or to guarantee `alignof(T) == alignof(Wrapper(T))`, it already has to differ from C on one of the platforms.

---

<div class="post-metadata">

**Author:** ![dgrunwald](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dgrunwald/32/3667_2.png) [@dgrunwald](https://internals.rust-lang.org/u/dgrunwald)\
**Post date:** [July 3, 2015, 5:24pm UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/8 "2015-07-03T17:24:49Z")

</div>

On unary types: “All structs that have a single positive-sized field of type T (?Sized or not) and no destructor can be safely transmuted between each-other, as well as T itself.”

Does this also imply that `&T` can be transmuted to `&UnaryStruct<T>`, even if the reference is pointing to a variable of type `T`? (this would be [quite useful](https://github.com/rust-lang/rfcs/issues/1106#issuecomment-116062961))

If yes, how does that interact with the point @petrochenkov is making in the case T=double?

---

<div class="post-metadata">

**Author:** ![Diggsey](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/diggsey/32/6311_2.png) [@Diggsey](https://internals.rust-lang.org/u/Diggsey)\
**Post date:** [July 3, 2015, 8:51pm UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/9 "2015-07-03T20:51:15Z")

</div>

I don't quite follow this paragraph:

> A repr(C) struct cannot have a ?Sized field. ... This of course implies tuples are not repr(C), and their padding is usually unspecified.

What do tuples have to do with having a ?Sized field?

One concern I have is with disallowing `repr(C)` on DSTs: it's fairly common in C code to use structs with a zero or one element fixed size array as the last field, whose closest translation to rust code would be a DST. `repr(fixed)` is not a great solution because a fixed layout does not imply a C-compatible layout.

What's the downside to making `repr(C)` more permissive - as long as there's a well defined C equivalent to a given rust type, `repr(C)` could work.

At the very least I'm against ignoring `repr(C)` and only issueing a warning: if it's ignored it should most definitely be an error, as the code almost certainly interfaces with C code and depends on the types being layout compatible. Backwards compatibility means that old code should still work, not that it should compile but then have undefined behaviour!

---

<div class="post-metadata">

**Author:** ![Gankra](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gankra/32/6002_2.png) [@Gankra](https://internals.rust-lang.org/u/Gankra)\
**Post date:** [July 3, 2015, 9:27pm UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/10 "2015-07-03T21:27:57Z")

</div>

> [@Diggsey](#):
>
> I don't quite follow this paragraph:

The tuple thing was based off the old coercions RFC, but tuples-have-a-dst-field has been rolled back in a later RFC. So that note is just erroneous now.

---

<div class="post-metadata">

**Author:** ![tbu](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tbu](https://internals.rust-lang.org/u/tbu)\
**Post date:** [July 6, 2015, 7:04pm UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/11 "2015-07-06T19:04:55Z")

</div>

> [@](#):
>
> Further, zero-sized types cannot influence the alignment or padding of a struct.

This is not the case as of today, if you include a zero-element array of some type, it makes the struct have at least the alignment of that type.

---

<div class="post-metadata">

**Author:** ![tbu](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tbu](https://internals.rust-lang.org/u/tbu)\
**Post date:** [July 6, 2015, 7:07pm UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/12 "2015-07-06T19:07:49Z")

</div>

Also, do we want to lock ourselves in with same pointer representation of zero-sized and non-zero-sized types?

---

<div class="post-metadata">

**Author:** ![stebalien](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/stebalien/32/228_2.png) [@stebalien](https://internals.rust-lang.org/u/stebalien)\
**Post date:** [July 15, 2015, 9:21pm UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/13 "2015-07-15T21:21:55Z")

</div>

Maybe this isn’t the right place to put this but can make interpreting allocated memory as `[u8]` UB? This would us to safely extend vectors without zeroing (and make IO more efficient). My rational is that the following _is_ safe (on linux at least) and is indistinguishable from allocating without zeroing.

```rust
use std::fs::File;
use std::io::prelude::*;
use std::io::SeekFrom;

fn fake_uninitialized() -> Vec<u8> {
    let mut v = Vec::new();
    v.reserve(100);

    let mut tmp_buf = vec![0; 100];
    let mut mem = File::open("/proc/self/mem").unwrap();
    mem.seek(SeekFrom::Start(v.as_ptr() as u64)).unwrap();
    assert!(mem.read(&mut tmp_buf[..]).unwrap() == 100);
    v.extend(tmp_buf);
    v
}

```

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:24am UTC](https://internals.rust-lang.org/t/pre-rfc-solidifying-repr-rust/2306/14 "2019-03-25T08:24:46Z")

</div>

Closed on March 25, 2019, 8:24am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
