const_builder/lib.rs
1//! Provides a [`ConstBuilder`] derive macro that generates a `*Builder` type
2//! that can be used to create a value with the builder pattern, even in a const
3//! context.
4//!
5//! The attributed type will gain an associated `builder` method, which can then
6//! be chained with function calls until all required fields are set, at which
7//! point you can call `build` to get the final value.
8//!
9//! Compile-time checks prevent setting the same field twice or calling `build`
10//! before all required fields are set.
11//!
12//! By default, the `*Builder` type and `*::builder` method have the same
13//! visibility as the type, and every field setter is `pub`, regardless of field
14//! visibility.
15//!
16//! The builder isn't clonable and its methods are called by-value, returning
17//! the updated builder value.
18//!
19//! The generated code is supported in `#![no_std]` crates.
20//!
21//! # Unsafety
22//!
23//! This derive macro generates `unsafe` code using
24//! [`MaybeUninit`](std::mem::MaybeUninit) to facilitate field-wise
25//! initialization of a struct, tracking initialized fields via const-generics.
26//! This broadly follows the guidance in the [nomicon section on unchecked
27//! uninitialized memory], and is, for now, required to get const-compatible
28//! builders for arbitrary types.
29//!
30//! # Struct Requirements
31//!
32//! All struct fields must be [`Sized`]. Fields using generic parameters may be
33//! [`?Sized`](Sized) for some parameters, as long as the actual instantiation
34//! of the builder only has [`Sized`] fields.
35//!
36//! When the struct is `#[repr(packed)]` and the last field may be
37//! [`?Sized`](Sized), the field must be attributed with
38//! `#[builder(unsized_tail)]` to replace the field drop code with an assert
39//! that the field cannot be dropped. Functionally, this combination of packed,
40//! unsized tails, and with the builder requirements means that this field has
41//! to be [`ManuallyDrop<T: ?Sized>`](std::mem::ManuallyDrop) or a wrapper
42//! around it.
43//!
44//! `enum` and `union` types are unsupported.
45//!
46//! # Default Values
47//!
48//! Fields can be attributed with `#[builder(default = None)]` or similar to
49//! be made optional by providing a default value.
50//!
51//! This default value will _not_ be dropped if it is overridden or the builder
52//! is dropped. Consequently, the value should be something that does not need
53//! to be dropped, such as a primitive, [`None`], [`String::new()`],
54//! [`Vec::new()`], [`Cow::Borrowed`](std::borrow::Cow), or similar.
55//!
56//! # API Stability
57//!
58//! The API of the emitted builder is considered forward-compatible as long as
59//! care is taken to ensure the surface area to consumers stays the same and the
60//! changes don't already constitute as breaking to consumers of the original
61//! struct.
62//!
63//! Because each field gets an associated const-generic parameter on the builder
64//! struct, even private fields with private setters will show up in the public
65//! API of the builder. To avoid exposing a field in the public API, use the
66//! `skip` attribute.
67//!
68//! Adding the `default` attribute to the struct or a field is
69//! forward-compatible. Removing the attribute is a breaking change.
70//!
71//! Additionally, changes to builder attributes that lead to reduction in
72//! visibility, renames, removal, or changes in signature of functions in the
73//! emitted code are also breaking changes. This includes attributes such `vis`,
74//! `rename`, `rename_fn`, `setter`, and `skip`.
75//!
76//! Major versions of this crate may also introduce breaking changes to the
77//! emitted structs. Minor versions will ensure to emit forward-compatible code.
78//!
79//! # Unchecked Builder
80//!
81//! There is also an `*UncheckedBuilder` without safety checks, which is private
82//! by default. While similar to the checked builder at a glance, not every
83//! attribute applies to it in the same way (f.e. the `setter` attribute has no
84//! effect), and its API isn't considered stable across source struct
85//! modifications, so it should not be exposed in stable public interfaces.
86//!
87//! This struct is used to simplify the implementation of the checked builder
88//! and it is exposed for users that want additional control.
89//!
90//! This builder works broadly in the same way as the checked builder, however:
91//!
92//! - initialized fields aren't tracked,
93//! - setting fields that were already set will forget the old value,
94//! - calling `build` is unsafe due to the lack of tracking, and
95//! - dropping it will forget all field values that were already set.
96//!
97//! You can convert between the checked and unchecked builder with
98//! `*Builder::into_unchecked` and `*UncheckedBuilder::assert_init`.
99//!
100//! # Example
101//!
102//! ```
103//! use const_builder::ConstBuilder;
104//!
105//! #[derive(ConstBuilder)]
106//! # #[derive(Debug, PartialEq)]
107//! pub struct Person<'a> {
108//! // fields are required by default
109//! pub name: &'a str,
110//! // optional fields have a default specified
111//! // the value is required even when the type implements `Default`!
112//! #[builder(default = 0)]
113//! pub age: u32,
114//! }
115//!
116//! let steve = const {
117//! Person::builder()
118//! .name("steve smith")
119//! .build()
120//! };
121//! # assert_eq!(
122//! # steve,
123//! # Person {
124//! # name: "steve smith",
125//! # age: 0,
126//! # }
127//! # );
128//! ```
129//!
130//! # Generated Interface
131//!
132//! The example above would generate an interface similar to the following. The
133//! actual generated code is more complex because it includes bounds to ensure
134//! fields are only written once and that the struct is fully initialized when
135//! calling `build`.
136//!
137//! ```
138//! # // This isn't an example to run, just an example "shape".
139//! # _ = stringify!(
140//! /// A builder type for [`Person`].
141//! pub struct PersonBuilder<'a, const _NAME: bool = false, const _AGE: bool = false> { ... }
142//!
143//! impl<'a, ...> PersonBuilder<'a, ...> {
144//! /// Creates a new builder.
145//! pub const fn new() -> Self;
146//!
147//! /// Returns the finished value.
148//! ///
149//! /// This function can only be called when all required fields have been set.
150//! pub const fn build(self) -> Person<'a>;
151//!
152//! // one setter function per field
153//! pub const fn name(self, value: &'a str) -> PersonBuilder<'a, ...>;
154//! pub const fn age(self, value: u32) -> PersonBuilder<'a, ...>;
155//!
156//! /// Unwraps this builder into its unsafe counterpart.
157//! ///
158//! /// This isn't unsafe in itself, however using it carelessly may lead to
159//! /// leaking objects and not dropping initialized values.
160//! const fn into_unchecked(self) -> PersonUncheckedBuilder<'a>;
161//! }
162//!
163//! impl<'a> Person<'a> {
164//! /// Creates a new builder for this type.
165//! pub const fn builder() -> PersonBuilder<'a>;
166//! }
167//!
168//! /// An _unchecked_ builder type for [`Person`].
169//! ///
170//! /// This version being _unchecked_ means it has less safety guarantees:
171//! /// - No tracking is done whether fields are initialized, so [`Self::build`] is `unsafe`.
172//! /// - If dropped, already initialized fields will be leaked.
173//! /// - The same field can be set multiple times. If done, the old value will be leaked.
174//! struct PersonUncheckedBuilder<'a> { ... }
175//!
176//! impl<'a> PersonUncheckedBuilder<'a> {
177//! /// Creates a new unchecked builder.
178//! pub const fn new() -> Self;
179//!
180//! /// Asserts that the fields specified by the const generics as well as all optional
181//! /// fields are initialized and promotes this value into a checked builder.
182//! ///
183//! /// # Safety
184//! ///
185//! /// The fields whose const generic are `true` and all optional fields have to be
186//! /// initialized.
187//! ///
188//! /// Optional fields are initialized by [`Self::new`] by default, however using
189//! /// [`Self::as_uninit`] allows de-initializing them. This means that this function
190//! /// isn't even necessarily safe to call if all const generics are `false`.
191//! pub const unsafe fn assert_init<const _NAME: bool, const _AGE: bool>(self) -> PersonBuilder<'a, _NAME, _AGE>;
192//!
193//! /// Returns the finished value.
194//! ///
195//! /// # Safety
196//! ///
197//! /// This function requires that all fields have been initialized.
198//! pub const unsafe fn build(self) -> Person<'a>;
199//!
200//! // one setter function per field
201//! pub const fn name(mut self, value: &'a str) -> Self;
202//! pub const fn age(mut self, value: u32) -> Self;
203//!
204//! /// Gets a mutable reference to the partially initialized data.
205//! pub const fn as_uninit(&mut self) -> &mut ::core::mem::MaybeUninit<Person<'a>>;
206//! }
207//! # );
208//! ```
209//!
210//! # Struct Attributes
211//!
212//! These attributes can be specified within `#[builder(...)]` on the struct
213//! level.
214//!
215//! | Attribute | Meaning |
216//! |:--------------------------- |:------- |
217//! | `default` | Generate a const-compatible `*::default()` function and [`Default`] derive. Requires every field to have a default value. |
218//! | `vis = "$vis"` | Change the visibility of the builder type. May be an empty string for private. Default is the same as the struct. |
219//! | `rename = $name` | Renames the builder type. Defaults to "`<Type>Builder`". |
220//! | `rename_fn = $name` | Renames the associated function that creates the builder. Defaults to `builder`. Set to `false` to disable. |
221//! | `unchecked(vis = "$vis")` | Change the visibility of the unchecked builder type. Default is private. |
222//! | `unchecked(rename = $name)` | Renames the unchecked builder type. Defaults to "`<Type>UncheckedBuilder`". |
223//!
224//! # Field Attributes
225//!
226//! These attributes can be specified within `#[builder(...)]` on the struct's
227//! fields.
228//!
229//! | Attribute | Meaning |
230//! |:------------------------------ |:------- |
231//! | `vis = "$vis"` | Change the visibility of the builder's field setter. May be an empty string for private. Default is `pub`. If you intend to hide the field from the public API, prefer `skip`. |
232//! | `default = $value` | Make the field optional by providing a default value. The value must be evaluatable in `const`. |
233//! | `rename = $name` | Renames the setters for this field. Defaults to the field name. |
234//! | `rename_generic = $name` | Renames the name of the associated const generic. Defaults to "`_{field:upper}`". |
235//! | `leak_on_drop` | Instead of dropping the field when dropping the builder, do nothing. |
236//! | `unsized_tail` | In a packed struct, marks the last field as potentially being unsized, replacing the drop code with an assert. No effect if the struct isn't packed. |
237//! | `setter(transform = $closure)` | Accepts closure syntax. The setter is changed to accept its inputs and set the corresponding value to its output. Parameter types are required. The closure body must be evaluatable in `const`. |
238//! | `setter(strip_option)` | On an [`Option<T>`] field, change the setter to accept `T` and wrap it in [`Some`] itself. Equivalent to `setter(transform = \|value: T\| Some(value))`. |
239//! | `skip` | Must be combined with `default`. Hides the field from the builder's public API by omitting its generic parameter and setter, instead forcing the default value. The unchecked builder retains a setter with the field's visibility. |
240//!
241//! # Attributes Example
242//!
243//! ```
244//! use const_builder::ConstBuilder;
245//!
246//! #[derive(ConstBuilder)]
247//! // change the builder from pub (same as Person) to crate-internal
248//! // also override the name of the builder to `CreatePerson`
249//! #[builder(vis = "pub(crate)", rename = "CreatePerson")]
250//! // change the unchecked builder from priv also to crate-internal
251//! #[builder(unchecked(vis = "pub(crate)"))]
252//! # #[derive(Debug, PartialEq)]
253//! pub struct Person<'a> {
254//! // required field with public setter
255//! name: &'a str,
256//! // optional field with public setter
257//! #[builder(default = 0)]
258//! age: u32,
259//! // skipped field omitted from builder interface
260//! #[builder(default = 1, skip)]
261//! version: u32,
262//! }
263//!
264//! # assert_eq!(
265//! # const {
266//! # Person::builder()
267//! # .name("smith")
268//! # .build()
269//! # },
270//! # Person {
271//! # name: "smith",
272//! # age: 0,
273//! # version: 1,
274//! # }
275//! # );
276//! ```
277//!
278//! [nomicon section on unchecked uninitialized memory]: https://doc.rust-lang.org/nomicon/unchecked-uninit.html
279
280#![forbid(unsafe_code)]
281#![warn(clippy::doc_markdown)]
282
283use proc_macro::TokenStream;
284use syn::{DeriveInput, parse_macro_input};
285
286mod const_builder_impl;
287mod model;
288mod util;
289
290/// Generates the builder types for the attributed struct.
291///
292/// See the crate-level documentation for more details.
293#[proc_macro_derive(ConstBuilder, attributes(builder))]
294pub fn derive_const_builder(input: TokenStream) -> TokenStream {
295 let input = parse_macro_input!(input as DeriveInput);
296 const_builder_impl::entry_point(input).into()
297}
298
299/// Not public API. This is an internal helper for compile-fail tests.
300///
301/// This fully discards the input token stream, allowing replacing the tested
302/// struct with an entirely different definition to test that safety-relevant
303/// mismatches lead to compilation errors.
304///
305/// Related rust issue: <https://github.com/rust-lang/rust/issues/148423>
306#[doc(hidden)]
307#[deprecated = "do not use, this is an internal test helper"]
308#[proc_macro_attribute]
309pub fn __discard_input_token_stream(_args: TokenStream, _input: TokenStream) -> TokenStream {
310 TokenStream::new()
311}
312
313/// I considered UI tests but since we still emit the code on almost all errors,
314/// there are a bunch of rustc diagnostics mixed in (when the compile error
315/// isn't literally just a rustc error). These aren't stable, so those tests
316/// would just break between language versions -- or even just stable and
317/// nightly.
318///
319/// ```compile_fail
320/// #[derive(const_builder::ConstBuilder)]
321/// struct TupleStruct(u32, u64);
322/// ```
323///
324/// ```compile_fail
325/// #[derive(const_builder::ConstBuilder)]
326/// struct UnitStruct;
327/// ```
328///
329/// ```compile_fail
330/// #[derive(const_builder::ConstBuilder)]
331/// enum Enum {
332/// B { a: u32, b: u64 },
333/// }
334/// ```
335///
336/// ```compile_fail
337/// #[derive(const_builder::ConstBuilder)]
338/// union Union {
339/// a: u32,
340/// b: u64,
341/// }
342/// ```
343///
344/// ```compile_fail
345/// #[derive(const_builder::ConstBuilder)]
346/// #[builder(default)]
347/// struct InvalidDefault {
348/// a: u32,
349/// #[builder(default = 0)]
350/// b: u32,
351/// }
352/// ```
353///
354/// ```compile_fail
355/// #[derive(const_builder::ConstBuilder)]
356/// struct DefaultNoValue {
357/// #[builder(default)]
358/// a: u32,
359/// }
360/// ```
361///
362/// ```compile_fail
363/// #[derive(const_builder::ConstBuilder)]
364/// struct WrongUnsizedTailPosition {
365/// #[builder(unsized_tail)]
366/// a: u32,
367/// b: u32,
368/// }
369/// ```
370///
371/// ```compile_fail
372/// // on stable, the macro code will not compile due to `UnsizedField: Sized`
373/// // bounds. however on nightly with `trivial_bounds`, the actual output of
374/// // the macro will compile, but the bounds will still prevent instantiating
375/// // or otherwise using the builder.
376/// // see also: https://github.com/rust-lang/rust/issues/48214
377/// #[derive(const_builder::ConstBuilder)]
378/// struct UnsizedField {
379/// a: [u32],
380/// }
381///
382/// // ensure instantiating fails anyways
383/// _ = UnsizedFieldBuilder::new();
384/// ```
385///
386/// ```compile_fail
387/// // this test actually fails for two reasons:
388/// // - rust disallowing possible-Drop unsized tails in packed structs
389/// // - static assert when a packed struct's `unsized_tail` field `needs_drop`
390/// #[derive(const_builder::ConstBuilder)]
391/// #[repr(Rust, packed)]
392/// struct PackedUnsizedDropTail<T: ?Sized> {
393/// #[builder(unsized_tail)]
394/// a: T,
395/// }
396///
397/// // ensure a variant with a `needs_drop` tail is instantiated
398/// _ = PackedUnsizedDropTail::<String>::builder();
399/// ```
400///
401/// ```compile_fail
402/// #[derive(const_builder::ConstBuilder)]
403/// struct SetterCastNoClosure {
404/// #[builder(setter(transform))]
405/// value: Option<u32>,
406/// }
407/// ```
408///
409/// ```compile_fail
410/// #[derive(const_builder::ConstBuilder)]
411/// struct SetterCastNotAClosure1 {
412/// #[builder(setter(transform = r#""hello""#))]
413/// value: Option<u32>,
414/// }
415/// ```
416///
417/// ```compile_fail
418/// #[derive(const_builder::ConstBuilder)]
419/// struct SetterCastNotAClosure2 {
420/// #[builder(setter(transform = 42))]
421/// value: Option<u32>,
422/// }
423/// ```
424///
425/// ```compile_fail
426/// #[derive(const_builder::ConstBuilder)]
427/// struct SetterCastNotAClosure3 {
428/// #[builder(setter(transform = Some(42)))]
429/// value: Option<u32>,
430/// }
431/// ```
432///
433/// ```compile_fail
434/// #[derive(const_builder::ConstBuilder)]
435/// struct SetterCastNoType {
436/// #[builder(setter(transform = |i| Some(i)))]
437/// value: Option<u32>,
438/// }
439/// ```
440///
441/// ```compile_fail
442/// #[derive(const_builder::ConstBuilder)]
443/// struct SetterCastNoTypePartial1 {
444/// #[builder(setter(transform = |a: u32, b| a + b))]
445/// value: u32,
446/// }
447/// ```
448///
449/// ```compile_fail
450/// #[derive(const_builder::ConstBuilder)]
451/// struct SetterCastNoTypePartial2 {
452/// #[builder(setter(transform = |a, b: u32| a + b))]
453/// value: u32,
454/// }
455/// ```
456///
457/// ```compile_fail
458/// // `works.rs` contains a similar case that compiles
459/// #[derive(ConstBuilder)]
460/// struct SetterCastPatNoType {
461/// #[builder(setter(transform = |Wrap(v)| v))]
462/// value: u32,
463/// }
464///
465/// struct Wrap<T>(T);
466/// ```
467///
468/// ```compile_fail
469/// #[derive(const_builder::ConstBuilder)]
470/// struct SetterCastAttrs {
471/// #[builder(setter(transform = (#[inline] |i: u32| Some(i))))]
472/// value: Option<u32>,
473/// }
474/// ```
475///
476/// ```compile_fail
477/// #[derive(const_builder::ConstBuilder)]
478/// struct SetterCastWrongLifetimes {
479/// #[builder(setter(transform = for<'b> |i: &'a u32| Some(*i)))]
480/// value: Option<u32>,
481/// }
482/// ```
483///
484/// ```compile_fail
485/// #[derive(const_builder::ConstBuilder)]
486/// struct SetterCastConst {
487/// #[builder(setter(transform = const |i: u32| Some(i)))]
488/// value: Option<u32>,
489/// }
490/// ```
491///
492/// ```compile_fail
493/// #[derive(const_builder::ConstBuilder)]
494/// struct SetterCastStatic {
495/// #[builder(setter(transform = static |i: u32| Some(i)))]
496/// value: Option<u32>,
497/// }
498/// ```
499///
500/// ```compile_fail
501/// #[derive(const_builder::ConstBuilder)]
502/// struct SetterCastAsync {
503/// #[builder(setter(transform = async |i: u32| Some(i)))]
504/// value: Option<u32>,
505/// }
506/// ```
507///
508/// ```compile_fail
509/// #[derive(const_builder::ConstBuilder)]
510/// struct SetterCastMove {
511/// #[builder(setter(transform = move |i: u32| Some(i)))]
512/// value: Option<u32>,
513/// }
514/// ```
515///
516/// ```compile_fail
517/// #[derive(const_builder::ConstBuilder)]
518/// struct SetterCastReturnType {
519/// #[builder(setter(transform = |i: u32| -> Option<u32> { Some(i) }))]
520/// value: Option<u32>,
521/// }
522/// ```
523///
524/// ```compile_fail
525/// #[derive(const_builder::ConstBuilder)]
526/// struct SetterCastAndStrip {
527/// #[builder(setter(strip_option, transform = |i: u32| Some(i)))]
528/// value: Option<u32>,
529/// }
530/// ```
531///
532/// ```compile_fail
533/// #[derive(const_builder::ConstBuilder)]
534/// struct SetterCastWrongType {
535/// #[builder(setter(transform = |v: u32| v))]
536/// value: i32,
537/// }
538/// ```
539///
540/// ```compile_fail
541/// #[derive(const_builder::ConstBuilder)]
542/// struct SetterUnknown {
543/// #[builder(setter(strip_result))]
544/// value: Result<u32, u32>,
545/// }
546/// ```
547///
548/// ```compile_fail
549/// #[derive(const_builder::ConstBuilder)]
550/// struct SetterStripOptionNotOption {
551/// #[builder(setter(strip_option))]
552/// value: Result<(), ()>,
553/// }
554/// ```
555///
556/// ```compile_fail
557/// #[derive(const_builder::ConstBuilder)]
558/// struct SetterStripOptionDefault {
559/// #[builder(default, setter(strip_option))]
560/// value: Option<u32>,
561/// }
562/// ```
563///
564/// ```compile_fail
565/// use core::marker::PhantomData;
566///
567/// #[derive(const_builder::ConstBuilder)]
568/// struct InvalidUse<T = u32> {
569/// #[builder(default = PhantomData)]
570/// marker: PhantomData<T>,
571/// }
572///
573/// // fails because it can't infer the generic type
574/// let value = InvalidUse::builder().build();
575/// ```
576///
577/// ```compile_fail
578/// #[derive(const_builder::ConstBuilder)]
579/// struct Incomplete1 {
580/// unset: bool,
581/// }
582///
583/// let value = Incomplete1::builder().build();
584/// ```
585///
586/// ```compile_fail
587/// #[derive(const_builder::ConstBuilder)]
588/// struct Incomplete2 {
589/// #[builder(default = false)]
590/// defaulted: bool,
591/// unset: bool,
592/// }
593///
594/// let value = Incomplete2::builder().build();
595/// ```
596///
597/// ```compile_fail
598/// #[derive(const_builder::ConstBuilder)]
599/// struct Incomplete3 {
600/// set: bool,
601/// unset: bool,
602/// }
603///
604/// let value = Incomplete3::builder().set(true).build();
605/// ```
606///
607/// ```compile_fail
608/// #[derive(const_builder::ConstBuilder)]
609/// struct DuplicateSet {
610/// field: bool,
611/// }
612///
613/// DuplicateSet::builder().field(true).field(true);
614/// ```
615///
616/// ```compile_fail
617/// #[derive(const_builder::ConstBuilder)]
618/// struct SkipNoDefault {
619/// #[builder(skip)]
620/// field: bool,
621/// }
622/// ```
623///
624/// ```compile_fail
625/// #[derive(const_builder::ConstBuilder)]
626/// struct SkipSetter {
627/// #[builder(skip, default = None, setter())]
628/// field: Option<u32>,
629/// }
630/// ```
631///
632/// ```compile_fail
633/// #[derive(const_builder::ConstBuilder)]
634/// struct SkipVis {
635/// #[builder(skip, default = None, vis = "pub")]
636/// field: Option<u32>,
637/// }
638/// ```
639///
640/// ```compile_fail
641/// #[derive(const_builder::ConstBuilder)]
642/// struct SkipRename {
643/// #[builder(skip, default = None, rename_generic = "_F")]
644/// field: Option<u32>,
645/// }
646/// ```
647///
648/// ```compile_fail
649/// #[derive(const_builder::ConstBuilder)]
650/// struct SkipNoSetter {
651/// #[builder(skip, default = None)]
652/// field: Option<u32>,
653/// }
654///
655/// // no setter
656/// _ = SkipNoSetter::builder().field(Some(0));
657/// ```
658///
659/// ```compile_fail
660/// mod inner {
661/// #[derive(const_builder::ConstBuilder)]
662/// #[builder(unchecked(vis = "pub"))]
663/// pub struct SkipPrivSetter {
664/// #[builder(skip, default = None)]
665/// field: Option<u32>,
666/// }
667/// }
668///
669/// // setter private
670/// _ = inner::SkipPrivSetterUncheckedBuilder::new().field(Some(0));
671/// ```
672///
673/// ```compile_fail
674/// // !! safety-relevant !!
675/// // a field not observed by the macro would allow
676/// // safe code to later read uninitialized memory.
677/// #[derive(const_builder::ConstBuilder)]
678/// #[const_builder::__discard_input_token_stream]
679/// struct AddsField {}
680/// struct AddsField {
681/// x: u32,
682/// }
683/// ```
684///
685/// ```compile_fail
686/// // this just fails because the builder tries to access
687/// // an unknown field.
688/// #[derive(const_builder::ConstBuilder)]
689/// #[const_builder::__discard_input_token_stream]
690/// struct RemovesField {
691/// x: u32,
692/// }
693/// struct RemovesField {}
694/// ```
695///
696/// ```compile_fail
697/// // !! safety-relevant !!
698/// // unaligned access requires a different emit because
699/// // writing to unaligned pointers is UB by default.
700/// // the inverse of this is fine, if not optimal.
701/// #[derive(const_builder::ConstBuilder)]
702/// #[const_builder::__discard_input_token_stream]
703/// struct ActuallyPacked {
704/// x: u32,
705/// }
706/// #[repr(C, packed)]
707/// struct ActuallyPacked {
708/// x: u32,
709/// }
710/// ```
711fn _compile_fail_test() {}