You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It is a breaking change to change the alignment, layout, or size of a type that was previously well-defined.
215
215
216
216
In general, types that use the [the default representation] do not have a well-defined alignment, layout, or size.
217
-
The compiler is free to alter the alignmentor layout, so code should not make any assumptions about it.
217
+
The compiler is free to alter the alignment, layout or size, so code should not make any assumptions about it.
218
218
219
219
> **Note**: It may be possible for external crates to break if they make assumptions about the alignment, layout, or size of a type even if it is not well-defined.
220
220
> This is not considered a SemVer breaking change since those assumptions should not be made.
221
221
222
222
Some examples of changes that are not a breaking change are (assuming no other rules in this guide are violated):
223
223
224
224
* Adding, removing, or changing fields of a default representation struct, union, or enum in such a way that the change follows the other rules in this guide (for example, using `non_exhaustive` to allow those changes, or changes to private fields that are already private).
225
+
See [struct-add-private-field-when-public](#struct-add-private-field-when-public), [struct-add-public-field-when-no-private](#struct-add-public-field-when-no-private), [struct-private-fields-with-private](#struct-private-fields-with-private), [enum-fields-new](#enum-fields-new).
225
226
* Adding variants to a default representation enum, if the enum uses `non_exhaustive`.
226
227
This may change the alignment or size of the enumeration, but those are not well-defined.
227
-
* Adding, removing, or changing private fields of a `repr(C)` struct, union, or enum.
228
-
Note that this may be a breaking change since it may change the size and alignment of the type.
229
-
Care should be taken in this case.
230
-
Adding private fields can only be done if there are already other private fields, or it is `non_exhaustive`.
231
-
Public fields may be added if there are private fields, or it is `non_exhaustive`, and the addition does not alter the layout of the other fields.
228
+
See [enum-variant-new](#enum-variant-new).
229
+
* Adding, removing, or changing private fields of a `repr(C)` struct, union, or enum, following the other rules in this guide (for example, using `non_exhaustive`, or adding private fields when other private fields already exist).
230
+
See [repr-c-private-change](#repr-c-private-change).
232
231
* Adding variants to a `repr(C)` enum, if the enum uses `non_exhastive`.
233
-
Note that this may be a breaking change since it may change the size and alignment of the type.
234
-
Care should be taken in this case.
232
+
See [repr-c-enum-variant-new](#repr-c-enum-variant-new).
235
233
* Adding `repr(C)` to a default representation struct, union, or enum.
234
+
See [repr-c-add](#repr-c-add).
236
235
* Adding `repr(<int>)`[primitive representation] to an enum.
236
+
See [repr-int-enum-add](#repr-int-enum-add).
237
237
* Adding `repr(transparent)` to a default representation struct or enum.
238
+
See [repr-transparent-add](#repr-transparent-add).
238
239
239
240
Nominal types that use the [`repr` attribute] can be said to have an alignment and layout that is defined in some way that code may make some assumptions about that may break as a result of changing that type.
240
241
241
242
Some examples of a breaking change are:
242
243
243
244
* Adding `repr(packed)` to a struct or union.
245
+
See [repr-packed-add](#repr-packed-add).
246
+
* Adding `repr(align)` to a struct, union, or enum.
247
+
See [repr-align-add](#repr-align-add).
248
+
* Removing `repr(packed)` from a struct or union.
249
+
See [repr-packed-remove](#repr-packed-remove).
250
+
* Changing the value N of `repr(packed(N))` if that changes the alignment or layout.
251
+
See [repr-packed-n-change](#repr-packed-n-change).
252
+
* Changing the value N of `repr(align(N))` if that changes the alignment.
253
+
See [repr-align-n-change](#repr-align-n-change).
254
+
* Removing `repr(align)` from a struct, union, or enum.
255
+
See [repr-align-remove](#repr-align-remove).
256
+
* Changing the order of public fields of a `repr(C)` type.
257
+
See [repr-c-shuffle](#repr-c-shuffle).
258
+
* Removing `repr(C)` from a struct, union, or enum.
259
+
See [repr-c-remove](#repr-c-remove).
260
+
* Removing `repr(<int>)` from an enum.
261
+
See [repr-int-enum-remove](#repr-int-enum-remove).
262
+
* Changing the primitive representation of a `repr(<int>)` enum.
263
+
See [repr-int-enum-change](#repr-int-enum-change).
264
+
* Removing `repr(transparent)` from a struct or enum.
265
+
See [repr-transparent-remove](#repr-transparent-remove).
244
266
245
-
Making a type `repr(packed)` makes changes that can break code, such as being invalid to take a reference to a field, or causing truncation of disjoint closure captures.
267
+
In some cases, types with a `repr` attribute may not have an alignment, layout, or size that is well-defined.
268
+
In these cases, it may be safe to make changes to the types, though care should be exercised.
269
+
For example, types with private fields that do not otherwise document their alignment, layout, or size guarantees cannot be relied upon by external crates since the public API does not fully define the alignment, layout, or size of the type.
246
270
247
-
<!-- TODO: If all fields are private, should this be safe to do? -->
271
+
A common example where a type with *private* fields is well-defined is a type with a single private field with a generic type, using `repr(transparent)`, and which is documented as being transparent to the generic type.
272
+
For example, see [`UnsafeCell`].
248
273
249
-
* Adding `repr(align)` to a struct, union, or enum.
Making a type `repr(align)` would break any use of that type in a `repr(packed)` type because that combination is not allowed.
280
+
<aid="repr-c-private-change"></a>
281
+
#### Minor: `repr(C)` add, remove, or change a private field
252
282
253
-
<!-- TODO: This seems like it should be extraordinarily rare. Should there be any exceptions carved out for this? -->
283
+
It is usually safe to add, remove, or change a private field of a `repr(C)` struct, union, or enum, assuming it follows the other guidelines in this guide (see [struct-add-private-field-when-public](#struct-add-private-field-when-public), [struct-add-public-field-when-no-private](#struct-add-public-field-when-no-private), [struct-private-fields-with-private](#struct-private-fields-with-private), [enum-fields-new](#enum-fields-new)).
254
284
255
-
* Removing `repr(packed)` from a struct or union.
285
+
For example, adding private fields can only be done if there are already other private fields, or it is `non_exhaustive`.
286
+
Public fields may be added if there are private fields, or it is `non_exhaustive`, and the addition does not alter the layout of the other fields.
256
287
257
-
This may change the alignment or layout that extern crates are relying on.
288
+
However, this may change the size and alignment of the type.
289
+
Care should be taken if the size or alignment changes.
290
+
Code should not make assumptions about the size or alignment of types with private fields or `non_exhaustive` unless it has a documented size or alignment.
258
291
259
-
If any fields are public, then removing `repr(packed)` may change the way disjoint closure captures work.
260
-
In some cases, this can cause code to break, similar to those outlined in the [edition guide][edition-closures].
292
+
```rust,ignore
293
+
// MINOR CHANGE
261
294
262
-
* Changing the value N of `repr(packed(N))` if that changes the alignment or layout.
// Example use of the library that will safely work.
316
+
fn main() {
317
+
// NOTE: Users should not make assumptions about the size or alignment
318
+
// since they are not documented.
319
+
let f = updated_crate::Example::default();
320
+
}
321
+
```
267
322
268
-
* Changing the value N of `repr(align(N))` if that changes the alignment.
323
+
<aid="repr-c-enum-variant-new"></a>
324
+
#### Minor: `repr(C)` add enum variant
269
325
270
-
This may change the alignment that external crates are relying on.
326
+
It is usually safe to add variants to a `repr(C)` enum, if the enum uses `non_exhastive`.
327
+
See [enum-variant-new](#enum-variant-new) for more discussion.
271
328
272
-
This change should be safe to make if the type is not well-defined as discussed below (such as having any private fields and having an undocumented alignment or layout).
329
+
Note that this may be a breaking change since it changes the size and alignment of the type.
330
+
See [repr-c-private-change](#repr-c-private-change) for similar concerns.
273
331
274
-
* Removing `repr(align)` from a struct, union, or enum.
332
+
```rust,ignore
333
+
// MINOR CHANGE
275
334
276
-
This may change the alignment or layout that external crates are relying on.
This change should be safe to make if the type is not well-defined as discussed below (such as having any private fields and having an undocumented alignment).
In some cases, types with a `repr` attribute may not have an alignment, layout, or size that is well-defined.
305
-
In these cases, it may be safe to make changes to the types, though care should be exercised.
306
-
For example, types with private fields that do not otherwise document their alignment, layout, or size guarantees cannot be relied upon by external crates since the public API does not fully define the alignment, layout, or size of the type.
// Example use of the library that will safely work.
423
+
fn main() {
424
+
let x = updated_crate::E::Variant3 { f1: 1.23 };
425
+
}
426
+
```
307
427
308
-
A common example where a type with *private* fields is well-defined is a type with a single private field with a generic type, using `repr(transparent)`, and which is documented as being transparent to the generic type.
428
+
<aid="repr-transparent-add"></a>
429
+
#### Minor: Adding `repr(transparent)` to a default representation struct or enum
309
430
431
+
It is safe to add `repr(transparent)` to a struct or enum with [the default representation].
432
+
This is safe because users should not make assumptions about the alignment, layout, or size of a struct or enum with the default representation.
// Example use of the library that will safely work.
450
+
fn main() {
451
+
let x = updated_crate::Example::<i32>::default();
452
+
}
453
+
```
454
+
455
+
<aid="repr-packed-add"></a>
456
+
#### Major: Adding `repr(packed)` to a struct or union
457
+
458
+
It is a breaking change to add `repr(packed)` to a struct or union.
459
+
Making a type `repr(packed)` makes changes that can break code, such as being invalid to take a reference to a field, or causing truncation of disjoint closure captures.
460
+
461
+
<!-- TODO: If all fields are private, should this be safe to do? -->
// When the structure was packed, the closure captures `p` which is Send.
631
+
// When `packed` is removed, this ends up capturing `p.a` which is not Send.
632
+
std::thread::spawn(move || unsafe {
633
+
*(p.a) += 1; // Error: cannot be sent between threads safely
634
+
});
635
+
}
636
+
```
637
+
638
+
<aid="repr-packed-n-change"></a>
639
+
#### Major: Changing the value N of `repr(packed(N))` if that changes the alignment or layout
640
+
641
+
It is a breaking change to change the value of N of `repr(packed(N))` if that changes the alignment or layout.
642
+
This may change the alignment or layout that external crates are relying on.
643
+
644
+
If the value `N` is lowered below the alignment of a public field, then that would break any code that attempts to take a reference of that field.
645
+
646
+
Note that some changes to `N` may not change the alignment or layout, for example increasing it when the current value is already equal to the natural alignment of the type.
let x = &p.b; // Error: reference to packed field is unaligned
674
+
}
675
+
```
676
+
677
+
<aid="repr-align-n-change"></a>
678
+
#### Major: Changing the value N of `repr(align(N))` if that changes the alignment
679
+
680
+
It is a breaking change to change the value `N` of `repr(align(N))` if that changes the alignment.
681
+
This may change the alignment that external crates are relying on.
682
+
683
+
This change should be safe to make if the type is not well-defined as discussed in [type layout](#type-layout) (such as having any private fields and having an undocumented alignment or layout).
684
+
685
+
Note that some changes to `N` may not change the alignment or layout, for example decreasing it when the current value is already equal to or less than the natural alignment of the type.
const _: () = assert!(std::mem::align_of::<Packed>() == 8); // Error: evaluation of constant value failed
715
+
}
716
+
```
717
+
718
+
<aid="repr-align-remove"></a>
719
+
#### Major: Removing `repr(align)` from a struct, union, or enum
720
+
721
+
It is a breaking change to remove `repr(align)` from a struct, union, or enum.
722
+
This may change the alignment or layout that external crates are relying on.
723
+
724
+
This change should be safe to make if the type is not well-defined as discussed in [type layout](#type-layout) (such as having any private fields and having an undocumented alignment).
0 commit comments