structural/lib.rs
1/*!
2
3This library provides field accessor traits,and emulation of structural types.
4
5# Features
6
7These are some of the features this library provides:
8
9- [`Structural`] derive macro to implement accessor traits for every public field:
10[`GetField`]/[`GetFieldMut`]/[`IntoField`] for structs,
11and [`GetVariantField`]/[`GetVariantFieldMut`]/[`IntoVariantField`] for enums.
12
13- The [`StructuralExt`] extension trait,which defines the main methods to access fields,
14so long as the type implements the accessor traits for those fields.
15
16- The [`StrucWrapper`] wrapper type,defined as an alternative to [`StructuralExt`].
17
18- The [`structural_alias`] macro, to declare trait aliases for accessor traits,
19using field-in-trait syntax.
20
21- The [`impl_struct`] macro to declare structural parameter/return types,
22as well as [`make_struct`] to construct anonymous structs
23
24- The [`FromStructural`] and [`TryFromStructural`] conversion traits,
25similar (but not identical) to the standard library `From` and `TryFrom` traits
26for structural types.
27
28
29# Clarifications
30
31The way that this library emulates structural types is by using traits as bounds
32or trait objects.
33
34All the `structural` traits are dyn-compatible(also known as object-safe),
35and no change will be made to make them not dyn-compatible.
36
37By default all structural types are open,
38structs and enums can have more variants and or fields than are required.<br>
39The only exception to this is exhaustive enums,
40in which the variant count and names must match exactly,
41this is useful for exhaustive matching of variants (in the [`switch`] macro).
42
43Every trait with the `_SI`/`_ESI`/`_VSI` suffixes in the examples are traits
44generated by the `Structural` derive macro.
45These traits alias the accessor traits implemented by the type they're named after.
46
47### Required macros
48
49The only macros that are required to use this crate are the ones for [`TStr`],
50every other macro expands to code that can be written manually
51(except for the [`__TS`] type,
52that is an implementation detail that only macros from
53this crate should use by name).
54
55<span id="root-mod-examples"></span>
56# Examples
57
58
59### Structural Derive for structs
60
61This demonstrates how you can use any type with a superset of the fields of
62another one in a function.
63
64[`Structural`] derive macro docs for more details on derivation.
65
66```rust
67use structural::{fp, Structural, StructuralExt};
68
69fn reads_point3<S>(point: &S)
70where
71 // The `Point3D_SI` trait was generated by the `Structural` derive for `Point3D`,
72 // aliasing the accessor traits implemented by `Point3D`.
73 S: Point3D_SI<u32>,
74{
75 let (a, b, c) = point.fields(fp!(x, y, z));
76
77 assert_eq!(a, &0);
78 assert_eq!(b, &11);
79 assert_eq!(c, &33);
80}
81
82fn main() {
83 reads_point3(&Point3D { x: 0, y: 11, z: 33 });
84
85 reads_point3(&Point4D {
86 x: 0,
87 y: 11,
88 z: 33,
89 a: 0xDEAD,
90 });
91
92 reads_point3(&Point5D {
93 x: 0,
94 y: 11,
95 z: 33,
96 a: 0xDEAD,
97 b: 0xBEEF,
98 });
99}
100
101#[derive(Structural)]
102// Using the `#[struc(public)]` attribute tells the derive macro to
103// generate the accessor trait impls for non-`pub` fields.
104#[struc(public)]
105struct Point3D<T> {
106 x: T,
107 y: T,
108 z: T,
109}
110
111#[derive(Structural)]
112// By default only public fields get accessor trait impls,
113// using `#[struc(public)]` you can have impls to access private fields.
114#[struc(public)]
115struct Point4D<T> {
116 x: T,
117 y: T,
118 z: T,
119 a: T,
120}
121
122#[derive(Structural)]
123struct Point5D<T> {
124 pub x: T,
125 pub y: T,
126 pub z: T,
127 pub a: T,
128 pub b: T,
129}
130
131```
132
133### Structural Derive for enums
134
135This demonstrates how you can use structural enums.
136
137For details on [enums look here](./docs/enums/index.html).
138
139```rust
140use structural::{fp, switch, Structural, StructuralExt};
141
142fn main() {
143 {
144 // Command
145
146 run_command(Command::SendEmail(SendEmail {
147 to: "ferris@lib.rs".to_string(),
148 content: "Hello".to_string(),
149 }));
150 run_command(Command::RemoveAddress("gopher".to_string()));
151 }
152 {
153 // ExtraCommand
154 //
155 // ExtraCommand can't be passed to `run_command` because that function requires
156 // an enum with exactly the `SendEmail` and `RemoveAddress` variants.
157
158 // The `SendEmail` variant can have more fields than the one in the `Command` enum,
159 // they're just ignored.
160 run_command_nonexhaustive(ExtraCommand::SendEmail {
161 to: "squatter@crates.io".to_string(),
162 content: "Can you stop squatting crate names?".to_string(),
163 topic: "squatting".to_string(),
164 })
165 .unwrap();
166
167 let ra_cmd = ExtraCommand::RemoveAddress("smart_person".to_string());
168 run_command_nonexhaustive(ra_cmd).unwrap();
169
170 let ca_cmd = ExtraCommand::CreateAddress("honest_person".to_string());
171 let res = run_command_nonexhaustive(ca_cmd.clone());
172 assert_eq!(res, Err(UnsupportedCommand(ca_cmd)));
173 }
174}
175
176// Runs the passed in command.
177//
178// The `Command_ESI` trait allows only enums with the same variants as
179// `Command` to be passed in(they can have a superset of the fields in `Command`).
180fn run_command<S>(cmd: S)
181where
182 S: Command_ESI,
183{
184 run_command_nonexhaustive(cmd)
185 .ok()
186 .expect("`run_command_nonexhaustive` must match all `Command` variants")
187}
188
189// Runs the passed in command.
190//
191// The `Command_SI` trait allows enums with a superset of the variants in `Command`
192// to be passed in,
193// requiring the a `_=>` branch when it's matched on with the `switch` macro.
194fn run_command_nonexhaustive<S>(cmd: S) -> Result<(), UnsupportedCommand<S>>
195where
196 S: Command_SI,
197{
198 switch! {cmd;
199 // This matches the SendEmail variant and destructures the
200 // `to` and `content` fields by value.
201 SendEmail{to,content}=>{
202 println!("Sending message to the '{}' email address.",to);
203 println!("Content:{:?}",content);
204 Ok(())
205 }
206 // This matches the RemoveAddress variant and destructures it into
207 // the 0th field (by reference,because of the `ref`).
208 ref RemoveAddress(address)=>{
209 println!("removing the '{}' email address",address);
210 Ok(())
211 }
212 _=>Err(UnsupportedCommand(cmd))
213 }
214}
215
216#[derive(Structural)]
217enum Command {
218 // The `newtype(bounds="...")` attribute marks the variant as being a newtype variant,
219 // delegating field accessors of the variant to `SendEmail`(its one field),
220 // as well as replacing the bounds for the variant in the
221 // trait aliases generated by the `Structural` derive (`Command_SI` and `Command_ESI`)
222 // with `SendEmail_VSI<TS!(SendEmail)>`.
223 //
224 // `SendEmail_VSI` was generated by the `Structural` derive on `SendEmail`,
225 // with accessor trait bounds for accessing the struct's fields
226 // in a variant (it takes the name of the variant as a generic parameter).
227 #[struc(newtype(bounds = "SendEmail_VSI<@variant>"))]
228 SendEmail(SendEmail),
229 RemoveAddress(String),
230}
231
232#[derive(Structural)]
233pub struct SendEmail {
234 pub to: String,
235 pub content: String,
236}
237
238#[derive(Debug, Structural, Clone, PartialEq)]
239// This attribute stops the generation of the
240// `ExtraCommands_SI` and `ExtraCommands_ESI` traits
241#[struc(no_trait)]
242pub enum ExtraCommand {
243 SendEmail {
244 to: String,
245 content: String,
246 topic: String,
247 },
248 RemoveAddress(String),
249 CreateAddress(String),
250}
251
252#[derive(Debug, PartialEq)]
253pub struct UnsupportedCommand<T>(pub T);
254```
255
256### Structural alias for struct
257
258This demonstrates how you can define a trait aliasing field accessors,
259using a fields-in-traits syntax.
260
261For more details you can look at the docs for the [`structural_alias`] macro.
262
263```rust
264
265use structural::{fp, structural_alias, FP, IntoFieldMut, Structural, StructuralExt};
266
267use std::borrow::Borrow;
268
269structural_alias! {
270 trait Person<H: House>{
271 name: String,
272 house: H,
273 }
274
275 trait House{
276 dim: Dimension3D,
277 }
278}
279
280fn print_name<T, H>(this: &T)
281where
282 T: ?Sized + Person<H>,
283
284 // This is the one trait that `House` requires in its blanket implementation.
285 // `H: House,` is equivalent to this
286 H: IntoFieldMut<FP!(dim), Ty = Dimension3D>,
287{
288 let (name, house_dim) = this.fields(fp!(name, house.dim));
289 println!("Hello, {}!", name);
290
291 let (w, h, d) = house_dim.fields(fp!(width, height, depth));
292
293 if w * h * d >= 1_000_000 {
294 println!("Your house is enormous.");
295 } else {
296 println!("Your house is normal sized.");
297 }
298}
299
300// most structural aliases are object safe
301fn print_name_dyn<H>(this: &dyn Person<H>)
302where
303 // This is the one trait that `House` requires in its blanket implementation.
304 // `H: House,` is equivalent to this
305 H: IntoFieldMut<FP!(dim), Ty = Dimension3D>,
306{
307 print_name(this)
308}
309
310#[derive(Structural)]
311#[struc(public)]
312struct Dimension3D {
313 width: u32,
314 height: u32,
315 depth: u32,
316}
317
318//////////////////////////////////////////////////////////////////////////
319//// The stuff here could be defined in a separate crate
320
321fn main() {
322 let worker = Worker {
323 name: "John Doe".into(),
324 salary: Cents(1_000_000_000_000_000),
325 house: Mansion {
326 dim: Dimension3D {
327 width: 300,
328 height: 300,
329 depth: 300,
330 },
331 money_vault_location: "In the basement".into(),
332 },
333 };
334
335 let student = Student {
336 name: "Jake English".into(),
337 birth_year: 1995,
338 house: SmallHouse {
339 dim: Dimension3D {
340 width: 30,
341 height: 30,
342 depth: 30,
343 },
344 residents: 10,
345 },
346 };
347
348 print_name(&worker);
349 print_name(&student);
350
351 print_name_dyn(&worker);
352 print_name_dyn(&student);
353}
354
355#[derive(Structural)]
356// Using the `#[struc(public)]` attribute tells the derive macro to
357// generate the accessor trait impls for non-`pub` fields.
358#[struc(public)]
359struct Worker {
360 name: String,
361 salary: Cents,
362 house: Mansion,
363}
364
365#[derive(Structural)]
366#[struc(public)]
367struct Student {
368 name: String,
369 birth_year: u32,
370 house: SmallHouse,
371}
372
373#[derive(Debug, Copy, Clone, PartialEq, Eq)]
374struct Cents(u64);
375
376#[derive(Structural)]
377#[struc(public)]
378struct Mansion {
379 dim: Dimension3D,
380 money_vault_location: String,
381}
382
383#[derive(Structural)]
384#[struc(public)]
385struct SmallHouse {
386 dim: Dimension3D,
387 residents: u32,
388}
389```
390
391### Structural alias for enums
392
393This demonstrates how you can use structural aliases for enums.
394
395This shows both exhaustive and nonexhaustive enum structural aliases.
396
397For more details you can look at the docs for the [`structural_alias`] macro.
398
399```rust
400use std::fmt::Debug;
401use structural::{fp, structural_alias, switch, Structural, StructuralExt};
402
403fn main() {
404 pet_animal_ex(&SomeMammals::Dog {
405 years: 1,
406 volume_cm3: 1,
407 });
408 pet_animal_ex(&SomeMammals::Horse);
409
410 // `MoreAnimals` cannot be passed to `pet_animal_ex`
411 // since that function requires an enum with only `Dog` and `Horse` variants.
412 assert_eq!(
413 pet_animal(&MoreAnimals::Dog {
414 years: 10,
415 volume_cm3: 100
416 }),
417 Ok(())
418 );
419 assert_eq!(pet_animal(&MoreAnimals::Horse), Ok(()));
420 assert_eq!(pet_animal(&MoreAnimals::Cat { lives: 9 }), Err(CouldNotPet));
421 assert_eq!(pet_animal(&MoreAnimals::Seal), Err(CouldNotPet));
422}
423
424// For an equivalent function that's ergonomic to write, look below for `pet_animal_switch`
425fn pet_animal(animal: &dyn Animal) -> Result<(), CouldNotPet> {
426 // `::Dog` accesses the `Dog` variant
427 // (without the `::` it'd be interpreted as a field access),
428 // The `=>` allows getting multiple fields from inside a nested field
429 // (this includes enum variants).
430 // `years,volume_cm3` are the field accessed from inside `::Dog`
431 let dog_fields = fp!(::Dog=>years,volume_cm3);
432
433 // The `is_horse` method comes from the `Animal` trait.
434 if animal.is_horse() {
435 println!("You are petting the horse");
436 } else if let Some((years, volume_cm3)) = animal.fields(dog_fields) {
437 println!(
438 "You are petting the {} year old,{} cm³ dog",
439 years, volume_cm3
440 );
441 } else {
442 return Err(CouldNotPet);
443 }
444 Ok(())
445}
446
447// This can't take a `&dyn Animal_Ex` because traits objects don't
448// automatically support upcasting into other trait objects
449// (except for auto traits like Send and Sync ).
450fn pet_animal_ex(animal: &impl Animal_Ex) {
451 pet_animal(animal).expect("`pet_animal` must match on all variants from the `Animal` trait");
452}
453
454// The same as `pet_animal` ,except that this uses the `switch` macro
455fn pet_animal_switch(animal: &dyn Animal) -> Result<(), CouldNotPet> {
456 switch! {animal;
457 Horse=>{
458 println!("You are petting the horse");
459 }
460 // This matches the Dog variant,
461 // and destructures it into its `years` and `volume_cm3` fields
462 // as references(because of the `ref`)
463 ref Dog{years,volume_cm3}=>{
464 println!("You are petting the {} year old,{} cm³ dog",years,volume_cm3);
465 }
466 _=>return Err(CouldNotPet)
467 }
468 Ok(())
469}
470
471#[derive(Debug, PartialEq)]
472struct CouldNotPet;
473
474structural_alias! {
475 // The `#[struc(and_exhaustive_enum(suffix = "_Ex"))]` attribute
476 // generates the `Animal_Ex` trait with this trait as a supertrait,
477 // and with the additional requirement that the enum
478 // only has the `Horse` and `Dog` variants
479 // (Those variants can still have more fields than required).
480 //
481 // structural aliases can have supertraits,here it's `Debug`
482 #[struc(and_exhaustive_enum(suffix = "_Ex"))]
483 trait Animal: Debug{
484 Horse,
485 Dog{years: u16, volume_cm3: u64},
486
487 // Structural aliases can define extension methods,
488 fn is_horse(&self) -> bool {
489 self.is_variant(fp!(Horse))
490 }
491 }
492}
493
494#[derive(Debug, Structural)]
495#[struc(no_trait)]
496enum SomeMammals {
497 Horse,
498 Dog { years: u16, volume_cm3: u64 },
499}
500
501#[derive(Debug, Structural)]
502#[struc(no_trait)]
503enum MoreAnimals {
504 Cat { lives: u8 },
505 Dog { years: u16, volume_cm3: u64 },
506 Horse,
507 Seal,
508}
509
510```
511
512### Anonymous structs (`make_struct` macro)
513
514This demonstrates how you can construct an anonymous struct.
515
516For more details you can look at the docs for the
517[`make_struct`](./macro.make_struct.html) macro.
518
519Docs for the [`impl_struct` macro](./macro.impl_struct.html).
520
521```rust
522use structural::{fp, impl_struct, make_struct, structural_alias, StructuralExt};
523
524structural_alias! {
525 trait Person<T>{
526 // We only have shared access (`&String`) to the field.
527 ref name: String,
528
529 // We have shared,mutable,and by value access to the field.
530 // Not specifying any of `mut`/`ref`/`move` is equivalent to `mut move value: T,`
531 value: T,
532 }
533}
534
535fn make_person(name: String) -> impl_struct! { name: String, value: () } {
536 make_struct! {
537 name,
538 value: (),
539 }
540}
541
542fn print_name(mut this: impl_struct! { ref name: String, value: Vec<String> }) {
543 println!("Hello, {}!", this.field_(fp!(name)));
544
545 let list = vec!["what".into()];
546 *this.field_mut(fp!(value)) = list.clone();
547 assert_eq!(this.field_(fp!(value)), &list);
548 assert_eq!(this.into_field(fp!(value)), list);
549}
550
551// most structural aliases are object safe
552//
553// This has to use the Person trait,
554// since `impl_struct!{....}` expands to `impl Trait0 + Trait1 + etc`.
555fn print_name_dyn(this: &mut dyn Person<Vec<String>>) {
556 println!("Hello, {}!", this.field_(fp!(name)));
557
558 let list = vec!["what".into()];
559 *this.field_mut(fp!(value)) = list.clone();
560 assert_eq!(this.field_(fp!(value)), &list);
561}
562
563//////////////////////////////////////////////////////////////////////////
564//// The stuff here could be defined in a separate crate
565
566fn main() {
567 let worker = make_struct! {
568 // This derives clone for the anonymous struct
569 #![derive(Clone)]
570 name: "John Doe".into(),
571 salary: Cents(1_000_000_000_000_000),
572 value: vec![],
573 };
574
575 let student = make_struct! {
576 // This derives clone for the anonymous struct
577 #![derive(Clone)]
578 name: "Jake English".into(),
579 birth_year: 1995,
580 value: vec![],
581 };
582
583 print_name(worker.clone());
584 print_name(student.clone());
585
586 print_name_dyn(&mut worker.clone());
587 print_name_dyn(&mut student.clone());
588
589 let person = make_person("Louis".into());
590
591 assert_eq!(person.field_(fp!(name)), "Louis");
592 assert_eq!(person.field_(fp!(value)), &());
593
594 // Destructuring the anonymous struct by value.
595 // The type annotation here is just to demonstrate that it returns a `String` by value.
596 let (name, value): (String, ()) = person.into_fields(fp!(name, value));
597 assert_eq!(name, "Louis");
598}
599
600#[derive(Debug, Copy, Clone, PartialEq, Eq)]
601struct Cents(u64);
602```
603
604[`Structural`]: ./docs/structural_macro/index.html
605[`GetField`]: ./field/trait.GetField.html
606[`GetFieldMut`]: ./field/trait.GetFieldMut.html
607[`IntoField`]: ./field/trait.IntoField.html
608[`GetVariantField`]: ./field/trait.GetVariantField.html
609[`GetVariantFieldMut`]: ./field/trait.GetVariantFieldMut.html
610[`IntoVariantField`]: ./field/trait.IntoVariantField.html
611
612[`StrucWrapper`]: ./struct.StrucWrapper.html
613
614[`StructuralExt`]: ./trait.StructuralExt.html
615[`impl_struct`]: ./macro.impl_struct.html
616[`make_struct`]: ./macro.make_struct.html
617[`structural_alias`]: ./macro.structural_alias.html
618[`switch`]: ./macro.switch.html
619
620[`__TS`]: ./struct.TStr.html#semver-concerns
621
622[`FromStructural`]: ./convert/trait.FromStructural.html
623[`TryFromStructural`]: ./convert/trait.TryFromStructural.html
624
625*/
626#![cfg_attr(feature = "nightly_impl_fields", feature(associated_type_bounds))]
627#![cfg_attr(feature = "nightly_specialization", feature(specialization))]
628#![cfg_attr(
629 all(feature = "nightly_use_const_str", not(feature = "disable_const_str")),
630 feature(const_if_match)
631)]
632#![cfg_attr(
633 all(feature = "nightly_use_const_str", not(feature = "disable_const_str")),
634 feature(const_generics)
635)]
636#![cfg_attr(
637 all(feature = "nightly_use_const_str", not(feature = "disable_const_str")),
638 allow(incomplete_features)
639)]
640#![deny(rust_2018_idioms)]
641#![allow(non_camel_case_types)]
642#![no_std]
643// The associated constants from this crate use trait bounds,
644// so they can't be translated to `const fn`.
645// Also,the constants don't use cell types,they're just generic.
646#![allow(clippy::declare_interior_mutable_const)]
647// This triggers for types that represent values, like `NestedFieldPath<(TS!(0), TS!(1))>`,
648// so it's mostly noise in this crate.
649#![allow(clippy::type_complexity)]
650// This lint is silly
651#![allow(clippy::blacklisted_name)]
652// This lint is silly
653#![allow(clippy::needless_doctest_main)]
654#![deny(clippy::missing_safety_doc)]
655#![deny(clippy::shadow_unrelated)]
656#![deny(clippy::wildcard_imports)]
657#![deny(missing_docs)]
658
659#[cfg(feature = "std")]
660#[doc(hidden)]
661pub extern crate std;
662
663#[doc(hidden)]
664pub extern crate core as std_;
665
666#[doc(hidden)]
667#[cfg(all(feature = "alloc"))]
668#[cfg_attr(feature = "hide_reexports", doc(hidden))]
669pub extern crate alloc;
670
671extern crate self as structural;
672
673pub use structural_derive::Structural;
674
675#[doc(hidden)]
676pub use structural_derive::{
677 _FP_impl_, _FP_literal_, _TStr_ident_impl_, _TStr_impl_, _TStr_lit_impl_,
678 _field_path_aliases_impl, _impl_struct_impl, _switch_tstring_aliases, _tstring_aliases_impl,
679 structural_alias_impl,
680};
681
682#[macro_use]
683mod macros;
684
685#[doc(hidden)]
686#[cfg(all(feature = "use_const_str", not(feature = "disable_const_str")))]
687pub mod const_generic_utils;
688pub mod convert;
689pub mod docs;
690pub mod enums;
691pub mod field;
692mod field_cloner;
693#[doc(hidden)]
694pub mod msg;
695pub mod path;
696pub mod structural_aliases;
697mod structural_ext;
698mod structural_trait;
699pub mod type_level;
700pub mod utils;
701mod wrapper;
702
703#[doc(hidden)]
704#[cfg(feature = "testing")]
705pub mod test_utils;
706
707#[doc(hidden)]
708#[cfg(feature = "testing")]
709pub mod tests;
710
711include! {"p.rs"}
712
713pub use crate::{
714 field::{
715 FieldType, GetField, GetFieldMut, GetFieldType, GetFieldType2, GetFieldType3,
716 GetFieldType4, GetVariantField, GetVariantFieldMut, GetVariantFieldType, IntoField,
717 IntoFieldMut, IntoVariantField, IntoVariantFieldMut,
718 },
719 field_cloner::FieldCloner,
720 structural_ext::StructuralExt,
721 structural_trait::Structural,
722 wrapper::StrucWrapper,
723};
724
725/// Reexports from other crates.
726///
727/// This reexports from `core_extensions`.
728pub mod reexports {
729 #[doc(no_inline)]
730 pub use core_extensions::{
731 collection_traits::{Cloned, ClonedOut, IntoArray},
732 const_default, ConstDefault,
733 };
734
735 #[cfg(feature = "alloc")]
736 #[cfg_attr(feature = "hide_reexports", doc(hidden))]
737 #[doc(no_inline)]
738 pub use crate::alloc::boxed::Box;
739}
740
741// pmr(proc macro reexports):
742// Reexports for the proc macros in structural_derive.
743//
744// Importing stuff from this module anywhere other than `structural_derive` is
745// explicitly disallowed,and is likely to break.
746#[doc(hidden)]
747pub mod pmr {
748 pub use crate::convert::*;
749 pub use crate::enums::variant_count::*;
750 pub use crate::enums::*;
751 pub use crate::field::ownership::*;
752 pub use crate::field::*;
753 pub use crate::path::*;
754 pub use crate::type_level::collection_traits::*;
755 pub use crate::type_level::*;
756 pub use crate::utils::{RunOnDrop, _Structural_BorrowSelf, as_phantomdata};
757 pub use core_extensions::{ConstDefault, MarkerType};
758
759 pub use crate::std_::{
760 convert::Infallible,
761 format_args,
762 marker::PhantomData,
763 mem::{drop, forget},
764 option::Option::{self, None, Some},
765 ptr::{drop_in_place, NonNull},
766 };
767
768 #[cfg(feature = "alloc")]
769 pub use crate::alloc::boxed::Box;
770}
771
772/// Structural-deriving types used in examples,
773///
774/// These are in the docs purely so that documentation examples only use
775/// types that are documented.
776///
777/// You can only use items from this module when the "for_examples" feature is enabled.
778#[cfg(any(feature = "for_examples", all(rust_1_41, doc)))]
779pub mod for_examples;
780
781/// Structural-deriving types used in examples,
782///
783/// You can only use items from this module when the "for_examples" feature is enabled.
784#[cfg(all(not(feature = "for_examples"), not(all(rust_1_41, doc))))]
785pub mod for_examples {}
786
787#[cfg(all(test, not(feature = "testing")))]
788compile_error! { "tests must be run with the \"testing\" feature" }
789
790//////////////////////////////
791
792use std_::marker::PhantomData;
793use std_::mem::ManuallyDrop;
794
795include! {"path/declare_field_path_types.rs"}