Skip to content

Commit 4ad9e69

Browse files
committed
Specify #[repr(transparent)]
1 parent 1f5d3a9 commit 4ad9e69

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

text/0000-repr-transparent.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
- Feature Name: `repr_transparent`
2+
- Start Date: 2016-09-26
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Extend the existing `#[repr]` attribute on newtypes with a `transparent` option
10+
specifying that the type representation is the representation of its only field.
11+
This matters in FFI context where `struct Foo(T)` might not behave the same
12+
as `T`.
13+
14+
15+
# Motivation
16+
[motivation]: #motivation
17+
18+
On some ABIs, structures with one field aren't handled the same way as values of
19+
the same type as the single field. For example on ARM64, functions returning
20+
a structure with a single `f64` field return nothing and take a pointer to be
21+
filled with the return value, whereas functions returning a `f64` return the
22+
floating-point number directly.
23+
24+
This means that if someone wants to wrap a `f64` value in a struct tuple
25+
wrapper and use that wrapper as the return type of a FFI function that actually
26+
returns a bare `f64`, the calls to this function will be compiled incorrectly
27+
by Rust and the execution of the program will segfault.
28+
29+
This also means that `UnsafeCell<T>` cannot be soundly used in place of a
30+
bare `T` in FFI context, which might be necessary to signal to the Rust side
31+
of things that this `T` value may unexpectedly be mutated.
32+
33+
```c
34+
// The value is returned directly in a floating-point register on ARM64.
35+
double do_something_and_return_a_double(void);
36+
```
37+
38+
```rust
39+
mod bogus {
40+
#[repr(C)]
41+
struct FancyWrapper(f64);
42+
43+
extern {
44+
// Incorrect: the wrapped value on ARM64 is indirectly returned and the
45+
// function takes a pointer to where the return value must be stored.
46+
fn do_something_and_return_a_double() -> FancyWrapper;
47+
}
48+
}
49+
50+
mod correct {
51+
#[repr(transparent)]
52+
struct FancyWrapper(f64);
53+
54+
extern {
55+
// Correct: FancyWrapper is handled exactly the same as f64 on all
56+
// platforms.
57+
fn do_something_and_return_a_double() -> FancyWrapper;
58+
}
59+
}
60+
```
61+
62+
Given this attribute delegates all representation concerns, no other `repr`
63+
attribute should be present on the type. This means the following definitions
64+
are illegal:
65+
66+
```rust
67+
#[repr(transparent, align = "128")]
68+
struct BogusAlign(f64);
69+
70+
#[repr(transparent, packed)]
71+
struct BogusPacked(f64);
72+
```
73+
74+
# Detailed design
75+
[design]: #detailed-design
76+
77+
The `#[repr]` attribute on newtypes will be extended to include a form such as:
78+
79+
```rust
80+
#[repr(transparent)]
81+
struct TransparentNewtype(f64);
82+
```
83+
84+
This structure will still have the same representation as a raw `f64` value.
85+
86+
Syntactically, the `repr` meta list will be extended to accept a meta item
87+
with the name "transparent". This attribute can be placed only on newtypes,
88+
which means structures (and structure tuples) with a single field.
89+
90+
Some examples of `#[repr(transparent)]` are:
91+
92+
```rust
93+
// Transparent struct tuple.
94+
#[repr(transparent)]
95+
struct TransparentStructTuple(i32);
96+
97+
// Transparent structure.
98+
#[repr(transparent)]
99+
struct TransparentStructure { only_field: f64 }
100+
```
101+
102+
This new representation is mostly useful when the structure it is put on must be
103+
used in FFI context as a wrapper to the underlying type without actually being
104+
affected by any ABI semantics.
105+
106+
It is also useful for `AtomicUsize`-like types, which [RFC 1649] states should
107+
have the same representation as their underlying types.
108+
109+
[RFC 1649]: https://github.com/rust-lang/rfcs/pull/1649
110+
111+
# Drawbacks
112+
[drawbacks]: #drawbacks
113+
114+
None.
115+
116+
# Alternatives
117+
[alternatives]: #alternatives
118+
119+
None.
120+
121+
# Unresolved questions
122+
[unresolved]: #unresolved-questions
123+
124+
* Should this representation be usable on structures that contain a single
125+
non-zero-sized field and `PhantomData` markers?

0 commit comments

Comments
 (0)