├── .gitignore ├── inception-test ├── src │ ├── lib.rs │ ├── data.rs │ ├── default.rs │ ├── eq.rs │ ├── hash.rs │ ├── debug.rs │ └── clone.rs ├── Cargo.toml └── benches │ └── comparison.rs ├── Cargo.toml ├── .github └── workflows │ └── ci.yml ├── inception ├── Cargo.toml └── src │ ├── lib.rs │ ├── meta.rs │ ├── ty.rs │ └── field.rs ├── inception-macros ├── src │ ├── lib.rs │ ├── primitive.rs │ └── derive.rs └── Cargo.toml ├── LICENSE ├── Cargo.lock ├── README.md └── STATIC_REFLECTION.md /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | paper/* 3 | !paper/inception.tex 4 | !paper/inception.pdf 5 | -------------------------------------------------------------------------------- /inception-test/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod clone; 2 | pub mod data; 3 | pub mod debug; 4 | pub mod default; 5 | pub mod eq; 6 | pub mod hash; 7 | -------------------------------------------------------------------------------- /inception-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "inception-test" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | inception = { workspace = true } 8 | 9 | [dev-dependencies] 10 | criterion = "0.7" 11 | 12 | [[bench]] 13 | name = "comparison" 14 | harness = false 15 | 16 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["inception", "inception-macros", "inception-test"] 3 | resolver = "2" 4 | 5 | [workspace.dependencies] 6 | deluxe = "0.5" 7 | quote = "1" 8 | paste = "1" 9 | proc-macro2 = "1" 10 | syn = { version = "2", features = ["full"] } 11 | inception = { path = "./inception" } 12 | inception-macros = { path = "./inception-macros", version = "0.1.0" } 13 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | pull_request: 5 | env: 6 | CARGO_TERM_COLOR: always 7 | jobs: 8 | check: 9 | name: Rust project - latest 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | toolchain: 14 | - stable 15 | steps: 16 | - uses: actions/checkout@v4 17 | - run: cargo check --workspace 18 | - run: cargo test --workspace 19 | -------------------------------------------------------------------------------- /inception/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "inception" 3 | description = "Automatic Trait Implementation by Induction" 4 | authors = ["Nick Senger"] 5 | edition = "2021" 6 | license = "MIT" 7 | repository = "https://github.com/nicksenger/inception" 8 | categories = ["science"] 9 | keywords = ["science", "no_std", "metaprogramming", "types", "dinosaurs"] 10 | rust-version = "1.84" 11 | version = "0.1.0" 12 | 13 | [features] 14 | default = ["opt", "opt-in"] 15 | opt = [] 16 | opt-in = ["inception-macros/opt-in"] 17 | 18 | [dependencies] 19 | inception-macros.workspace = true 20 | -------------------------------------------------------------------------------- /inception-macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_attributes)] 2 | extern crate quote; 3 | extern crate syn; 4 | 5 | use proc_macro::TokenStream; 6 | 7 | mod derive; 8 | mod inception; 9 | mod primitive; 10 | 11 | #[proc_macro_derive(Inception, attributes(inception))] 12 | pub fn derive(input: TokenStream) -> TokenStream { 13 | derive::State::gen(input) 14 | } 15 | 16 | #[proc_macro_attribute] 17 | pub fn inception(attr: TokenStream, item: TokenStream) -> TokenStream { 18 | inception::State::gen(attr, item) 19 | } 20 | 21 | #[proc_macro_attribute] 22 | pub fn primitive(attr: TokenStream, item: TokenStream) -> TokenStream { 23 | primitive::State::gen(attr, item) 24 | } 25 | -------------------------------------------------------------------------------- /inception-macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "inception-macros" 3 | description = "Macros for Inception" 4 | authors = ["Nick Senger "] 5 | edition = "2021" 6 | license = "MIT" 7 | repository = "https://github.com/nicksenger/inception" 8 | categories = ["science"] 9 | keywords = ["science", "no_std", "metaprogramming", "types", "dinosaurs"] 10 | rust-version = "1.84" 11 | version = "0.1.0" 12 | 13 | [lib] 14 | proc-macro = true 15 | 16 | [features] 17 | default = ["opt-in"] 18 | opt-in = [] 19 | 20 | [dependencies] 21 | deluxe = { workspace = true } 22 | proc-macro2 = { workspace = true } 23 | quote = { workspace = true } 24 | syn = { features = ["full"], workspace = true } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2025 Nick Senger 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /inception-test/src/data.rs: -------------------------------------------------------------------------------- 1 | use inception::Inception; 2 | 3 | use crate::clone::{DupeMut, DupeOwned, DupeRef}; 4 | use crate::debug::{DebugRef, DebugTy}; 5 | use crate::default::Default; 6 | use crate::eq::SameSame; 7 | use crate::hash::Digestible; 8 | 9 | #[derive(Inception)] 10 | #[inception(properties = [Default, Digestible, SameSame, DebugTy, DebugRef, DupeRef, DupeMut, DupeOwned])] 11 | pub struct Actor { 12 | pub name: String, 13 | pub kind: Kind, 14 | pub net_worth: u128, 15 | } 16 | 17 | #[derive(Inception)] 18 | #[inception(properties = [Default, Digestible, SameSame, DebugTy, DebugRef, DupeRef, DupeMut, DupeOwned])] 19 | pub enum Kind { 20 | BigName { salary: u64 }, 21 | Aspiring { salary: u8 }, 22 | } 23 | 24 | #[derive(Inception)] 25 | #[inception(properties = [Default, Digestible, SameSame, DebugTy, DebugRef, DupeRef, DupeMut, DupeOwned])] 26 | pub struct Movie { 27 | pub title: String, 28 | pub year: u64, 29 | pub lead: Actor, 30 | pub also_important: Actor, 31 | pub director: Director, 32 | } 33 | 34 | #[derive(Inception)] 35 | #[inception(properties = [Default, Digestible, SameSame, DebugTy, DebugRef, DupeRef, DupeMut, DupeOwned])] 36 | pub struct Director { 37 | pub name: String, 38 | pub num_movies: u8, 39 | pub age: u8, 40 | } 41 | 42 | #[derive(Inception)] 43 | #[inception(properties = [Default, Digestible, SameSame, DebugTy, DebugRef, DupeRef, DupeMut, DupeOwned])] 44 | pub enum Version { 45 | One(Movie), 46 | Two(Movie), 47 | } 48 | -------------------------------------------------------------------------------- /inception-test/src/default.rs: -------------------------------------------------------------------------------- 1 | use inception::*; 2 | 3 | #[inception(property = Default)] 4 | pub trait Standard { 5 | fn standard() -> Self; 6 | 7 | fn nothing() -> List<()> { 8 | List(()) 9 | } 10 | fn merge, R: Standard::Owned>>( 11 | _l: L, 12 | _r: R, 13 | ) -> ::Owned { 14 | List((H::standard().into(), R::standard())) 15 | } 16 | fn merge_variant_field, R: Standard::Owned>>( 17 | _l: L, 18 | _r: R, 19 | ) -> ::Owned { 20 | List((VarOwnedField::new(H::standard()), R::standard())) 21 | } 22 | fn join>::OwnedFields>>(_fields: F) -> Self { 23 | >::from_fields(F::standard()) 24 | } 25 | } 26 | 27 | #[primitive(property = Default)] 28 | impl Standard for u8 { 29 | fn standard() -> Self { 30 | 0 31 | } 32 | } 33 | #[primitive(property = Default)] 34 | impl Standard for u64 { 35 | fn standard() -> Self { 36 | 0 37 | } 38 | } 39 | #[primitive(property = Default)] 40 | impl Standard for u128 { 41 | fn standard() -> Self { 42 | 0 43 | } 44 | } 45 | #[primitive(property = Default)] 46 | impl Standard for String { 47 | fn standard() -> Self { 48 | std::default::Default::default() 49 | } 50 | } 51 | #[primitive(property = Default)] 52 | impl Standard for VariantHeader { 53 | fn standard() -> Self { 54 | VariantHeader 55 | } 56 | } 57 | 58 | #[cfg(test)] 59 | mod test { 60 | use super::*; 61 | use crate::data::Movie; 62 | 63 | #[test] 64 | fn default() { 65 | let _s = Movie::standard(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /inception-macros/src/primitive.rs: -------------------------------------------------------------------------------- 1 | use proc_macro::TokenStream; 2 | use quote::quote; 3 | use syn::{parse_macro_input, ItemImpl, Path}; 4 | 5 | #[derive(deluxe::ParseMetaItem, deluxe::ExtractAttributes)] 6 | #[deluxe(attributes(primitive))] 7 | struct Attributes { 8 | property: Path, 9 | } 10 | 11 | pub struct State {} 12 | impl State { 13 | pub fn gen(attr: TokenStream, item: TokenStream) -> TokenStream { 14 | let input = parse_macro_input!(item as syn::Item); 15 | match input { 16 | syn::Item::Impl(ref x) => { 17 | let ItemImpl { 18 | trait_: Some(_t), 19 | self_ty, 20 | .. 21 | } = x 22 | else { 23 | return syn::Error::new_spanned( 24 | x, 25 | "This macro can only be applied to trait implementations.", 26 | ) 27 | .to_compile_error() 28 | .into(); 29 | }; 30 | let Ok(Attributes { property }) = deluxe::parse(attr) else { 31 | return syn::Error::new_spanned(x, "Expected \"property = ...\"") 32 | .into_compile_error() 33 | .into(); 34 | }; 35 | let (impl_generics, ty_generics, where_clause) = x.generics.split_for_impl(); 36 | 37 | quote! { 38 | #input 39 | const _: () = { 40 | impl #impl_generics ::inception::IsPrimitive<#property> for #self_ty #ty_generics #where_clause { 41 | type Is = <#property as ::inception::Compat>::Out; 42 | } 43 | }; 44 | } 45 | .into() 46 | } 47 | item => syn::Error::new_spanned( 48 | item, 49 | "This macro can only be applied to trait implementations.", 50 | ) 51 | .to_compile_error() 52 | .into(), 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /inception-test/benches/comparison.rs: -------------------------------------------------------------------------------- 1 | use criterion::{criterion_group, criterion_main, Criterion}; 2 | 3 | use inception_test::clone::Duplicate; 4 | use inception_test::data::Version; 5 | use inception_test::default::Standard; 6 | use inception_test::eq::Same; 7 | use inception_test::hash::Digest; 8 | 9 | #[derive(Clone, Default, PartialEq, Eq, Hash)] 10 | pub struct Actor2 { 11 | pub name: String, 12 | pub kind: Kind2, 13 | pub net_worth: u128, 14 | } 15 | #[derive(Clone, PartialEq, Eq, Hash)] 16 | pub enum Kind2 { 17 | BigName { salary: u64 }, 18 | Aspiring { salary: u8 }, 19 | } 20 | impl Default for Kind2 { 21 | fn default() -> Self { 22 | Self::BigName { salary: u64::MAX } 23 | } 24 | } 25 | #[derive(Clone, Default, PartialEq, Eq, Hash)] 26 | pub struct Movie2 { 27 | pub title: String, 28 | pub year: u64, 29 | pub lead: Actor2, 30 | pub also_important: Actor2, 31 | pub director: Director2, 32 | } 33 | 34 | #[derive(Clone, Default, PartialEq, Eq, Hash)] 35 | pub struct Director2 { 36 | pub name: String, 37 | pub num_movies: u8, 38 | pub age: u8, 39 | } 40 | 41 | #[derive(Clone, PartialEq, Eq, Hash)] 42 | pub enum Version2 { 43 | One(Movie2), 44 | Two(Movie2), 45 | } 46 | impl Default for Version2 { 47 | fn default() -> Self { 48 | Self::One(Movie2::default()) 49 | } 50 | } 51 | 52 | pub fn criterion_benchmark(c: &mut Criterion) { 53 | use std::hash::Hash; 54 | let mut h = std::hash::DefaultHasher::new(); 55 | let data1 = Version::standard(); 56 | let data2 = Version2::default(); 57 | c.bench_function("dupe 20", |b| b.iter(|| data1.dupe())); 58 | c.bench_function("clone 20", |b| b.iter(|| data2.clone())); 59 | c.bench_function("standard 20", |b| b.iter(Version::standard)); 60 | c.bench_function("default 20", |b| b.iter(Version2::default)); 61 | c.bench_function("same 20", |b| b.iter(|| data1.same(&data1))); 62 | c.bench_function("eq 20", |b| b.iter(|| data2.eq(&data2))); 63 | c.bench_function("digest 20", |b| b.iter(|| data1.digest(&mut h))); 64 | c.bench_function("hash 20", |b| b.iter(|| data2.hash(&mut h))); 65 | } 66 | 67 | criterion_group!(benches, criterion_benchmark); 68 | criterion_main!(benches); 69 | -------------------------------------------------------------------------------- /inception-test/src/eq.rs: -------------------------------------------------------------------------------- 1 | use inception::*; 2 | 3 | #[inception(property = SameSame, comparator)] 4 | pub trait Same { 5 | fn same(&self, _other: &Self) -> bool; 6 | 7 | fn nothing() -> bool { 8 | true 9 | } 10 | fn merge, R: Same>(l: L, r: R, l2: L, r2: R) -> bool { 11 | l.access().same(l2.access()) && r.same(&r2) 12 | } 13 | fn merge_variant_field, R: Same>( 14 | l: L, 15 | r: R, 16 | l2: L, 17 | r2: R, 18 | ) -> bool { 19 | match (l.try_access(), l2.try_access()) { 20 | (Ok(l), Ok(l2)) => l.same(l2) && r.same(&r2), 21 | (Err(_), Err(_)) => true, 22 | _ => false, 23 | } 24 | } 25 | fn join>(fields: F, fields2: F) -> bool { 26 | fields.same(&fields2) 27 | } 28 | } 29 | 30 | #[primitive(property = SameSame)] 31 | impl Same for u8 { 32 | fn same(&self, other: &Self) -> bool { 33 | self == other 34 | } 35 | } 36 | #[primitive(property = SameSame)] 37 | impl Same for u64 { 38 | fn same(&self, other: &Self) -> bool { 39 | self == other 40 | } 41 | } 42 | #[primitive(property = SameSame)] 43 | impl Same for u128 { 44 | fn same(&self, other: &Self) -> bool { 45 | self == other 46 | } 47 | } 48 | #[primitive(property = SameSame)] 49 | impl Same for String { 50 | fn same(&self, other: &Self) -> bool { 51 | self == other 52 | } 53 | } 54 | #[primitive(property = SameSame)] 55 | impl Same for VariantHeader { 56 | fn same(&self, _other: &Self) -> bool { 57 | true 58 | } 59 | } 60 | 61 | pub trait Different { 62 | fn different(&self, other: &Self) -> bool; 63 | } 64 | impl Different for T 65 | where 66 | T: Same, 67 | { 68 | fn different(&self, other: &Self) -> bool { 69 | !self.same(other) 70 | } 71 | } 72 | 73 | #[cfg(test)] 74 | mod test { 75 | use crate::data::Movie; 76 | use crate::default::Standard; 77 | 78 | use super::*; 79 | 80 | #[test] 81 | fn sameness() { 82 | let m = Movie::standard(); 83 | assert!(m.same(&m)); 84 | } 85 | 86 | #[test] 87 | fn different() { 88 | let m = Movie::standard(); 89 | assert!(!m.different(&m)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /inception-test/src/hash.rs: -------------------------------------------------------------------------------- 1 | use inception::*; 2 | 3 | #[inception(property = Digestible)] 4 | pub trait Digest { 5 | fn digest(&self, state: &mut std::hash::DefaultHasher) -> (); 6 | 7 | fn nothing() -> bool { 8 | true 9 | } 10 | fn merge(l: L, r: R, state: &mut std::hash::DefaultHasher) -> () { 11 | l.access().digest(state); 12 | r.digest(state); 13 | } 14 | fn merge_variant_field( 15 | l: L, 16 | r: R, 17 | state: &mut std::hash::DefaultHasher, 18 | ) -> () { 19 | if let Ok(value) = l.try_access() { 20 | value.digest(state); 21 | } 22 | r.digest(state); 23 | } 24 | fn join(fields: F, state: &mut std::hash::DefaultHasher) -> () { 25 | fields.digest(state); 26 | } 27 | } 28 | 29 | use std::hash::Hash; 30 | #[primitive(property = Digestible)] 31 | impl Digest for u8 { 32 | fn digest(&self, state: &mut std::hash::DefaultHasher) { 33 | use std::hash::Hash; 34 | self.hash(state); 35 | } 36 | } 37 | #[primitive(property = Digestible)] 38 | impl Digest for u64 { 39 | fn digest(&self, state: &mut std::hash::DefaultHasher) { 40 | use std::hash::Hash; 41 | self.hash(state); 42 | } 43 | } 44 | #[primitive(property = Digestible)] 45 | impl Digest for u128 { 46 | fn digest(&self, state: &mut std::hash::DefaultHasher) { 47 | use std::hash::Hash; 48 | self.hash(state); 49 | } 50 | } 51 | #[primitive(property = Digestible)] 52 | impl Digest for String { 53 | fn digest(&self, state: &mut std::hash::DefaultHasher) { 54 | self.hash(state); 55 | } 56 | } 57 | #[primitive(property = Digestible)] 58 | impl Digest for VariantHeader { 59 | fn digest(&self, _state: &mut std::hash::DefaultHasher) {} 60 | } 61 | 62 | #[cfg(test)] 63 | mod test { 64 | use std::hash::Hasher; 65 | 66 | use crate::data::{Actor, Movie}; 67 | use crate::default::Standard; 68 | 69 | use super::*; 70 | 71 | #[test] 72 | fn digest() { 73 | use std::hash::DefaultHasher; 74 | let mut h = DefaultHasher::new(); 75 | let inception = Movie::standard(); 76 | inception.digest(&mut h); 77 | let a = h.finish(); 78 | 79 | let mut h = DefaultHasher::new(); 80 | let leo = Actor::standard(); 81 | leo.digest(&mut h); 82 | let b = h.finish(); 83 | 84 | assert_ne!(a, b); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /inception/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | pub use field::{Field, Fields}; 4 | pub use inception_macros::{inception, primitive, Inception}; 5 | pub use meta::{ 6 | DataType, EnumMeta, EnumTy, FieldsMeta, IsPrimitive, Meta, NamedFieldsMeta, StructMeta, 7 | StructTy, UnnamedFieldsMeta, VariantOffset, 8 | }; 9 | pub use ty::{ 10 | Compat, False, IntoTuples, List, Mask, Pad, Pad0, Pad1, Pad2, Pad3, Pad4, Pad5, Pad6, Pad7, 11 | Pad8, SplitOff, SplitOffInfix, True, TruthValue, PAD_0, PAD_1, PAD_2, PAD_3, PAD_4, PAD_5, 12 | PAD_6, PAD_7, PAD_8, 13 | }; 14 | 15 | pub mod field; 16 | pub mod meta; 17 | pub mod ty; 18 | 19 | pub use field::{ 20 | Access, Empty, MutEnumAccessError, MutField, OwnedEnumAccessError, OwnedField, Phantom, 21 | RefEnumAccessError, RefField, TryAccess, TyField, VarField, VarMutField, VarOwnedField, 22 | VarRefField, VarTyField, VariantHeader, 23 | }; 24 | pub use ty::Nothing; 25 | 26 | pub trait Property {} 27 | pub trait OptIn {} 28 | 29 | pub trait Inception>::Is>: 30 | IsPrimitive + DataType 31 | { 32 | type TyFields: field::Fields + field::Phantom; 33 | type RefFields<'a>: field::Fields 34 | where 35 | Self: 'a; 36 | type MutFields<'a>: field::Fields 37 | where 38 | Self: 'a; 39 | type OwnedFields: field::Fields; 40 | 41 | fn ty_fields() -> Self::TyFields { 42 | Self::TyFields::phantom() 43 | } 44 | fn fields(&self) -> Self::RefFields<'_>; 45 | fn fields_mut<'a: 'b, 'b>( 46 | &'a mut self, 47 | variant_header: &'b mut VariantHeader, 48 | ) -> Self::MutFields<'b>; 49 | fn into_fields(self) -> Self::OwnedFields; 50 | fn from_fields(fields: Self::OwnedFields) -> Self; 51 | } 52 | 53 | pub trait Split { 54 | type Left; 55 | type Right; 56 | 57 | fn split(self) -> (Self::Left, Self::Right); 58 | } 59 | pub trait SplitTy { 60 | type Left; 61 | type Right; 62 | 63 | fn split_ty(self) -> (Self::Left, Self::Right); 64 | } 65 | pub trait SplitRef { 66 | type Left; 67 | type Right; 68 | 69 | fn split_ref(&self) -> (Self::Left, &Self::Right); 70 | } 71 | pub trait SplitMut { 72 | type Left; 73 | type Right; 74 | 75 | fn split_mut(&mut self) -> (Self::Left, &mut Self::Right); 76 | } 77 | 78 | pub trait Wrapper { 79 | type Content; 80 | fn wrap(t: Self::Content) -> Self; 81 | } 82 | impl Phantom for T 83 | where 84 | T: Wrapper, 85 | ::Content: Phantom, 86 | { 87 | fn phantom() -> Self { 88 | ::wrap(<::Content as Phantom>::phantom()) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /inception/src/meta.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | 3 | use crate::{field::VarField, False, Field, Fields, Property, True, TruthValue}; 4 | 5 | pub trait DataType { 6 | const NAME: &str; 7 | type Ty; 8 | } 9 | pub struct InternalTy; 10 | pub struct EnumTy; 11 | pub struct StructTy(PhantomData); 12 | 13 | impl DataType for T 14 | where 15 | T: Fields, 16 | { 17 | const NAME: &str = "Fields"; 18 | type Ty = InternalTy; 19 | } 20 | 21 | pub trait EnumMeta: DataType { 22 | const VARIANT_NAMES: &[&str]; 23 | const FIELD_NAMES: &[&[&str]]; 24 | } 25 | pub trait Meta::Ty>: DataType { 26 | fn metadata() -> Metadata; 27 | } 28 | impl Meta for T 29 | where 30 | T: Fields + DataType, 31 | { 32 | fn metadata() -> Metadata { 33 | Metadata::Internal 34 | } 35 | } 36 | impl Meta for T 37 | where 38 | T: EnumMeta + DataType, 39 | { 40 | fn metadata() -> Metadata { 41 | Metadata::Enum { 42 | name: ::NAME, 43 | variant_names: ::VARIANT_NAMES, 44 | field_names: ::FIELD_NAMES, 45 | } 46 | } 47 | } 48 | pub trait StructMeta: DataType { 49 | const NUM_FIELDS: usize; 50 | type NamedFields: TruthValue; 51 | } 52 | impl Meta> for T 53 | where 54 | T: StructMeta + NamedFieldsMeta + DataType, 55 | { 56 | fn metadata() -> Metadata { 57 | Metadata::Struct { 58 | name: ::NAME, 59 | field_names: ::FIELD_NAMES, 60 | } 61 | } 62 | } 63 | impl Meta> for T 64 | where 65 | T: StructMeta + UnnamedFieldsMeta + DataType, 66 | { 67 | fn metadata() -> Metadata { 68 | Metadata::Struct { 69 | name: ::NAME, 70 | field_names: &[], 71 | } 72 | } 73 | } 74 | 75 | pub trait NamedFieldsMeta::Ty>: DataType { 76 | const FIELD_NAMES: &[&str]; 77 | } 78 | pub trait UnnamedFieldsMeta::Ty>: DataType { 79 | const NUM_FIELDS: usize; 80 | } 81 | 82 | pub trait FieldsMeta::Ty>: DataType { 83 | type Named: TruthValue; 84 | } 85 | impl FieldsMeta> for T 86 | where 87 | T: StructMeta + DataType>, 88 | { 89 | type Named = True; 90 | } 91 | impl FieldsMeta> for T 92 | where 93 | T: StructMeta + DataType>, 94 | { 95 | type Named = False; 96 | } 97 | impl FieldsMeta for T 98 | where 99 | T: EnumMeta, 100 | { 101 | type Named = False; 102 | } 103 | impl FieldsMeta for T 104 | where 105 | T: Fields, 106 | { 107 | type Named = True; 108 | } 109 | 110 | #[derive(Debug)] 111 | pub enum Metadata { 112 | Enum { 113 | name: &'static str, 114 | variant_names: &'static [&'static str], 115 | field_names: &'static [&'static [&'static str]], 116 | }, 117 | Struct { 118 | name: &'static str, 119 | field_names: &'static [&'static str], 120 | }, 121 | Internal, 122 | } 123 | 124 | pub enum FieldsMetadata { 125 | Named { names: &'static [&'static str] }, 126 | Unnamed { len: usize }, 127 | } 128 | 129 | pub trait IsPrimitive { 130 | type Is: TruthValue; 131 | } 132 | 133 | pub trait VariantOffset { 134 | type Padding; 135 | const PADDING: Self::Padding; 136 | } 137 | 138 | pub trait VariantMeta { 139 | const VARIANT_NAME: &str; 140 | const VARIANT_FIELD_NAMES: &[&str]; 141 | } 142 | impl VariantMeta for T 143 | where 144 | T: VarField, 145 | ::Source: EnumMeta, 146 | { 147 | const VARIANT_NAME: &str = 148 | <::Source as EnumMeta>::VARIANT_NAMES[::VAR_IDX]; 149 | const VARIANT_FIELD_NAMES: &[&str] = 150 | <::Source as EnumMeta>::FIELD_NAMES[::VAR_IDX]; 151 | } 152 | -------------------------------------------------------------------------------- /inception-test/src/debug.rs: -------------------------------------------------------------------------------- 1 | use inception::{field::VarField, meta::VariantMeta, *}; 2 | 3 | #[inception(property = DebugTy)] 4 | trait DiagTy { 5 | fn diag() -> String; 6 | 7 | fn nothing() -> String { 8 | Default::default() 9 | } 10 | 11 | fn merge, R: DiagTy>(_t: L, _f: R) -> String { 12 | let l = ::diag().to_string(); 13 | let r = ::diag(); 14 | format!("{l}\n{r}") 15 | } 16 | 17 | fn merge_variant_field, R: DiagTy>( 18 | _t: L, 19 | _f: R, 20 | ) -> String { 21 | let l = format!( 22 | "{}: {}", 23 | ::IDX, 24 | ::diag() 25 | ); 26 | let r = ::diag(); 27 | format!("{l}\n{r}") 28 | } 29 | 30 | fn join>(_f: F) -> String { 31 | let content = ::diag() 32 | .lines() 33 | .map(|l| format!(" {l}")) 34 | .collect::>() 35 | .join("\n"); 36 | format!("{} {{\n{content}\n}}", Self::NAME) 37 | } 38 | } 39 | 40 | #[primitive(property = DebugTy)] 41 | impl DiagTy for u8 { 42 | fn diag() -> String { 43 | "u8".to_string() 44 | } 45 | } 46 | #[primitive(property = DebugTy)] 47 | impl DiagTy for u64 { 48 | fn diag() -> String { 49 | "u64".to_string() 50 | } 51 | } 52 | #[primitive(property = DebugTy)] 53 | impl DiagTy for u128 { 54 | fn diag() -> String { 55 | "u128".to_string() 56 | } 57 | } 58 | #[primitive(property = DebugTy)] 59 | impl DiagTy for String { 60 | fn diag() -> String { 61 | "String".to_string() 62 | } 63 | } 64 | #[primitive(property = DebugTy)] 65 | impl DiagTy for VariantHeader { 66 | fn diag() -> String { 67 | "__variant__".to_string() 68 | } 69 | } 70 | 71 | #[inception(property = DebugRef)] 72 | pub trait DiagRef { 73 | fn print(&self) -> String; 74 | 75 | fn nothing() -> String { 76 | Default::default() 77 | } 78 | 79 | fn merge, R: DiagRef>(l: L, r: R) -> String { 80 | let l = format!("{}: {}", ::IDX, l.access().print()); 81 | let r = r.print(); 82 | format!("{l}\n{r}") 83 | } 84 | 85 | fn merge_variant_field, R: DiagRef>( 86 | l: L, 87 | r: R, 88 | ) -> String { 89 | let l = format!( 90 | "{}: {}", 91 | ::IDX, 92 | match l.try_access() { 93 | Ok(f) => format!( 94 | "{}: {}", 95 | ::VARIANT_FIELD_NAMES 96 | .get(::IDX) 97 | .unwrap_or(&"unnamed"), 98 | f.print() 99 | ), 100 | Err(RefEnumAccessError::Header(_)) => 101 | format!("[[{}]]", ::VARIANT_NAME), 102 | Err(RefEnumAccessError::EmptyField(_)) => ::VARIANT_FIELD_NAMES 103 | .get(::IDX) 104 | .unwrap_or(&"unnamed") 105 | .to_string(), 106 | } 107 | ); 108 | let r = r.print(); 109 | format!("{l}\n{r}") 110 | } 111 | 112 | fn join>(f: F) -> String { 113 | let content = f 114 | .print() 115 | .lines() 116 | .map(|l| format!(" {l}")) 117 | .collect::>() 118 | .join("\n"); 119 | format!("{} {{\n{content}\n}}", Self::NAME) 120 | } 121 | } 122 | 123 | #[primitive(property = DebugRef)] 124 | impl DiagRef for u8 { 125 | fn print(&self) -> String { 126 | self.to_string() 127 | } 128 | } 129 | #[primitive(property = DebugRef)] 130 | impl DiagRef for u64 { 131 | fn print(&self) -> String { 132 | self.to_string() 133 | } 134 | } 135 | #[primitive(property = DebugRef)] 136 | impl DiagRef for u128 { 137 | fn print(&self) -> String { 138 | self.to_string() 139 | } 140 | } 141 | #[primitive(property = DebugRef)] 142 | impl DiagRef for String { 143 | fn print(&self) -> String { 144 | self.clone() 145 | } 146 | } 147 | #[primitive(property = DebugRef)] 148 | impl DiagRef for VariantHeader { 149 | fn print(&self) -> String { 150 | "__variant__".to_string() 151 | } 152 | } 153 | 154 | #[cfg(test)] 155 | mod test { 156 | use super::{DiagTy, *}; 157 | use crate::data::Movie; 158 | 159 | #[test] 160 | fn tydiag() { 161 | let s = Movie::diag(); 162 | println!("{s}"); 163 | } 164 | 165 | #[test] 166 | fn refdiag() { 167 | use crate::default::Standard; 168 | 169 | let data = Movie::standard(); 170 | let s = data.print(); 171 | println!("{s}"); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /inception-test/src/clone.rs: -------------------------------------------------------------------------------- 1 | use inception::*; 2 | 3 | #[inception(property = DupeRef)] 4 | pub trait Duplicate { 5 | fn dupe(&self) -> Self; 6 | 7 | fn nothing() -> List<()> { 8 | List(()) 9 | } 10 | fn merge, R: Duplicate::Owned>>( 11 | l: L, 12 | r: R, 13 | ) -> ::Owned { 14 | List((l.access().dupe().into(), r.dupe())) 15 | } 16 | fn merge_variant_field, R: Duplicate::Owned>>( 17 | l: L, 18 | r: R, 19 | ) -> ::Owned { 20 | match l.try_access() { 21 | Ok(f) => List((VarOwnedField::new(f.dupe()), r.dupe())), 22 | Err(RefEnumAccessError::Header(d)) => { 23 | List((VarOwnedField::header(d.access().dupe()), r.dupe())) 24 | } 25 | Err(_) => List((VarOwnedField::empty(), r.dupe())), 26 | } 27 | } 28 | fn join>::OwnedFields>>(fields: F) -> Self { 29 | >::from_fields(fields.dupe()) 30 | } 31 | } 32 | 33 | #[primitive(property = DupeRef)] 34 | impl Duplicate for u8 { 35 | fn dupe(&self) -> Self { 36 | *self 37 | } 38 | } 39 | #[primitive(property = DupeRef)] 40 | impl Duplicate for u64 { 41 | fn dupe(&self) -> Self { 42 | *self 43 | } 44 | } 45 | #[primitive(property = DupeRef)] 46 | impl Duplicate for u128 { 47 | fn dupe(&self) -> Self { 48 | *self 49 | } 50 | } 51 | #[primitive(property = DupeRef)] 52 | impl Duplicate for String { 53 | fn dupe(&self) -> Self { 54 | self.clone() 55 | } 56 | } 57 | #[primitive(property = DupeRef)] 58 | impl Duplicate for VariantHeader { 59 | fn dupe(&self) -> Self { 60 | VariantHeader 61 | } 62 | } 63 | 64 | #[inception(property = DupeMut)] 65 | trait MutDupe { 66 | fn dupe_mut(&mut self) -> Self; 67 | 68 | fn nothing() -> List<()> { 69 | List(()) 70 | } 71 | fn merge, R: MutDupe::Owned>>( 72 | l: L, 73 | r: R, 74 | ) -> ::Owned { 75 | List((l.access().dupe_mut().into(), r.dupe_mut())) 76 | } 77 | fn merge_variant_field, R: MutDupe::Owned>>( 78 | l: L, 79 | r: R, 80 | ) -> ::Owned { 81 | match l.try_access() { 82 | Ok(f) => List((VarOwnedField::new(f.dupe_mut()), r.dupe_mut())), 83 | Err(MutEnumAccessError::Header(d)) => { 84 | List((VarOwnedField::header(d.access().dupe_mut()), r.dupe_mut())) 85 | } 86 | Err(_) => List((VarOwnedField::empty(), r.dupe_mut())), 87 | } 88 | } 89 | fn join>::OwnedFields>>(fields: F) -> Self { 90 | >::from_fields(fields.dupe_mut()) 91 | } 92 | } 93 | 94 | #[primitive(property = DupeMut)] 95 | impl MutDupe for u8 { 96 | fn dupe_mut(&mut self) -> Self { 97 | *self 98 | } 99 | } 100 | #[primitive(property = DupeMut)] 101 | impl MutDupe for u64 { 102 | fn dupe_mut(&mut self) -> Self { 103 | *self 104 | } 105 | } 106 | #[primitive(property = DupeMut)] 107 | impl MutDupe for u128 { 108 | fn dupe_mut(&mut self) -> Self { 109 | *self 110 | } 111 | } 112 | #[primitive(property = DupeMut)] 113 | impl MutDupe for String { 114 | fn dupe_mut(&mut self) -> Self { 115 | self.clone() 116 | } 117 | } 118 | #[primitive(property = DupeMut)] 119 | impl MutDupe for VariantHeader { 120 | fn dupe_mut(&mut self) -> Self { 121 | VariantHeader 122 | } 123 | } 124 | 125 | #[inception(property = DupeOwned)] 126 | trait OwnDupe { 127 | fn dupe_owned(self) -> Self; 128 | 129 | fn nothing() -> List<()> { 130 | List(()) 131 | } 132 | fn merge, R: OwnDupe::Owned>>( 133 | l: L, 134 | r: R, 135 | ) -> ::Owned { 136 | List((l.access().dupe_owned().into(), r.dupe_owned())) 137 | } 138 | fn merge_variant_field, R: OwnDupe::Owned>>( 139 | l: L, 140 | r: R, 141 | ) -> ::Owned { 142 | match l.try_access() { 143 | Ok(f) => List((VarOwnedField::new(f.dupe_owned()), r.dupe_owned())), 144 | Err(OwnedEnumAccessError::Header(d)) => List(( 145 | VarOwnedField::header(d.access().dupe_owned()), 146 | r.dupe_owned(), 147 | )), 148 | Err(_) => List((VarOwnedField::empty(), r.dupe_owned())), 149 | } 150 | } 151 | fn join>::OwnedFields>>(fields: F) -> Self { 152 | >::from_fields(fields.dupe_owned()) 153 | } 154 | } 155 | 156 | #[primitive(property = DupeOwned)] 157 | impl OwnDupe for u8 { 158 | fn dupe_owned(self) -> Self { 159 | self 160 | } 161 | } 162 | #[primitive(property = DupeOwned)] 163 | impl OwnDupe for u64 { 164 | fn dupe_owned(self) -> Self { 165 | self 166 | } 167 | } 168 | #[primitive(property = DupeOwned)] 169 | impl OwnDupe for u128 { 170 | fn dupe_owned(self) -> Self { 171 | self 172 | } 173 | } 174 | #[primitive(property = DupeOwned)] 175 | impl OwnDupe for String { 176 | fn dupe_owned(self) -> Self { 177 | self.clone() 178 | } 179 | } 180 | #[primitive(property = DupeOwned)] 181 | impl OwnDupe for VariantHeader { 182 | fn dupe_owned(self) -> Self { 183 | VariantHeader 184 | } 185 | } 186 | 187 | #[test] 188 | fn clone() { 189 | use crate::data::Movie; 190 | use crate::default::Standard; 191 | let mut data = Movie::standard(); 192 | 193 | data.dupe_mut(); 194 | data.dupe(); 195 | data.dupe_owned(); 196 | } 197 | -------------------------------------------------------------------------------- /inception/src/ty.rs: -------------------------------------------------------------------------------- 1 | type E = (); 2 | 3 | #[macro_export] 4 | macro_rules! list { 5 | [$(,)?] => { $crate::ty::List(()) }; 6 | [$a:expr$(,)?] => { $crate::ty::List(($a, $crate::ty::List(()))) }; 7 | [$a:expr,$($bs:expr),+$(,)?] => { $crate::ty::List(($a, $crate::list![$($bs),+])) }; 8 | } 9 | #[macro_export] 10 | macro_rules! list_ty { 11 | [$(,)?] => { $crate::ty::List<()> }; 12 | [$a:ty$(,)?] => { $crate::ty::List::<($a, $crate::ty::List<()>)> }; 13 | [$a:ty,$($bs:ty),+$(,)?] => { $crate::ty::List::<($a, $crate::list_ty![$($bs),+])> }; 14 | } 15 | 16 | macro_rules! unbounded { 17 | [$a:ident] => { $crate::ty::List($a) }; 18 | [$a:ident,$b:ident$(,)?] => { $crate::ty::List(($a, $b)) }; 19 | [$a:ident,$($bs:ident),+$(,)?] => { $crate::ty::List(($a, unbounded![$($bs),+])) }; 20 | } 21 | macro_rules! unbounded_ty { 22 | [$a:ty] => { $crate::ty::List::<$a> }; 23 | [$a:ty,$b:ty$(,)?] => { $crate::ty::List::<($a, $b)> }; 24 | [$a:ty,$($bs:ty),+$(,)?] => { $crate::ty::List::<($a, unbounded_ty![$($bs),+])> }; 25 | } 26 | macro_rules! unpack { 27 | [$(,)?] => { 28 | List(()) 29 | }; 30 | [$id:ident $(,)? $($ids:ident),*] => { 31 | List(($id, unpack![$($ids),*])) 32 | }; 33 | } 34 | macro_rules! padding { 35 | [$($n:ident,$m:ident => [$($tts:tt),*]),*] => { 36 | $(pub type $m = list_ty![$($tts),*];)* 37 | $(pub const $n: $m = list![$($tts),*];)* 38 | }; 39 | } 40 | padding![ 41 | PAD_0, Pad0 => [], 42 | PAD_1, Pad1 => [()], 43 | PAD_2, Pad2 => [(), ()], 44 | PAD_3, Pad3 => [(), (), ()], 45 | PAD_4, Pad4 => [(), (), (), ()], 46 | PAD_5, Pad5 => [(), (), (), (), ()], 47 | PAD_6, Pad6 => [(), (), (), (), (), ()], 48 | PAD_7, Pad7 => [(), (), (), (), (), (), ()], 49 | PAD_8, Pad8 => [(), (), (), (), (), (), (), ()] 50 | ]; 51 | 52 | pub trait Interleave { 53 | type Out; 54 | fn interleave(self, rhs: Rhs) -> Self::Out; 55 | } 56 | 57 | macro_rules! interleave { 58 | [($($a:ident)? , $($b:ident)?) -> ($($c:ident)? , $($d:ident)?)] => { 59 | impl< $($a)? $($b)? > Interleave for list_ty![$($a)?] { 60 | type Out = list_ty![$($a)? $($b)?]; 61 | fn interleave(self, unpack![$($d)?]: list_ty![$($b)?]) -> Self::Out { 62 | let unpack![$($c)?] = self; 63 | list![$($c)?$($d)?] 64 | } 65 | } 66 | }; 67 | [([$a:ident$(,)?$($as:ident),*], [$b:ident$(,)?$($bs:ident),*]) -> ([$($cs:ident),*], [$($ds:ident),*])] => { 68 | impl< $a,$b,$($as,$bs),* > Interleave for list_ty![$a,$($as),*] 69 | where list_ty![$($as),*]: Interleave { 70 | type Out = list_ty![$a,$b,$($as,$bs),*]; 71 | fn interleave(self, unpack![$($ds),*]: list_ty![$b,$($bs),*]) -> Self::Out { 72 | let unpack![$($cs),*] = self; 73 | list![$($cs,$ds),*] 74 | } 75 | } 76 | }; 77 | [[$a:ident$(,)?$($as:ident),* : $y:ident], [$b:ident$(,)?$($bs:ident),* : $z:ident] => [$($cs:ident),* : $ys:ident], [$($ds:ident),* : $zs:ident]] => { 78 | impl< $a,$b,$y,$z,$($as,$bs),* > Interleave for unbounded_ty![$a,$($as),* , $y] 79 | where $y: Interleave<$z> { 80 | type Out = unbounded_ty![$a,$b,$($as,$bs),* , <$y as Interleave<$z>>::Out]; 81 | fn interleave(self, unbounded![$($ds),* , $zs]: unbounded_ty![$b,$($bs),* , $z]) -> Self::Out { 82 | let unbounded![$($cs),* , $ys] = self; 83 | let tail = $ys.interleave($zs); 84 | unbounded![$($cs,$ds),* , tail] 85 | } 86 | } 87 | }; 88 | } 89 | interleave![(,) -> (,)]; 90 | interleave![(,B) -> (,b)]; 91 | interleave![(A,) -> (a,)]; 92 | interleave![([A], [B]) -> ([a], [b])]; 93 | #[cfg(not(feature = "opt"))] 94 | interleave![[A, C: E], [B, D: F] => [a, c: e], [b, d: f]]; 95 | #[cfg(feature = "opt")] 96 | const _: () = { 97 | interleave![([A, C], [B, D]) -> ([a, c], [b, d])]; 98 | interleave![([A, C, E], [B, D, F]) -> ([a, c, e], [b, d, f])]; 99 | interleave![([A, C, E, G], [B, D, F, H]) -> ([a, c, e, g], [b, d, f, h])]; 100 | interleave![([A, C, E, G, I], [B, D, F, H, J]) -> ([a, c, e, g, i], [b, d, f, h, j])]; 101 | interleave![([A, C, E, G, I, K], [B, D, F, H, J, L]) -> ([a, c, e, g, i, k], [b, d, f, h, j, l])]; 102 | interleave![([A, C, E, G, I, K, M], [B, D, F, H, J, L, N]) -> ([a, c, e, g, i, k, m], [b, d, f, h, j, l, n])]; 103 | interleave![([A, C, E, G, I, K, M, O], [B, D, F, H, J, L, N, P]) -> ([a, c, e, g, i, k, m, o], [b, d, f, h, j, l, n, p])]; 104 | interleave![[A, C, E, G, I, K, M, O, Q : S], [B, D, F, H, J, L, N, P, R : T] => [a, c, e, g, i, k, m, o, q: s], [b, d, f, h, j, l,n,p,r:t]]; 105 | }; 106 | 107 | pub trait Compat { 108 | type Out: TruthValue; 109 | } 110 | 111 | pub struct True; 112 | pub struct False; 113 | pub trait TruthValue {} 114 | impl TruthValue for True {} 115 | impl TruthValue for False {} 116 | 117 | pub type Nothing = List<()>; 118 | pub struct List(pub T); 119 | impl List<(T, U)> { 120 | pub fn split(self) -> (T, U) { 121 | (self.0 .0, self.0 .1) 122 | } 123 | } 124 | 125 | pub trait IntoTuples { 126 | type Left; 127 | type Right; 128 | fn into_tuples(self) -> (Self::Left, Self::Right); 129 | } 130 | impl IntoTuples for List<()> { 131 | type Left = (); 132 | type Right = (); 133 | fn into_tuples(self) -> (Self::Left, Self::Right) { 134 | ((), ()) 135 | } 136 | } 137 | macro_rules! into_tuples { 138 | [([$a:ident$(,)?$($as:ident),*])] => { 139 | impl< $a,$($as),* > IntoTuples for list_ty![$a,$($as),*] { 140 | type Left = $a; 141 | type Right = (::Left, ::Right); 142 | fn into_tuples(self) -> (Self::Left, Self::Right) { 143 | (self.0 .0, self.0 .1.into_tuples()) 144 | } 145 | } 146 | }; 147 | [[$a:ident,$($as:ident),+]] => { 148 | impl< $a,$($as),* > IntoTuples for unbounded_ty![$a,$($as),*] 149 | where unbounded_ty![$($as),*]: IntoTuples { 150 | type Left = $a; 151 | type Right = (::Left, ::Right); 152 | fn into_tuples(self) -> (Self::Left, Self::Right) { 153 | (self.0 .0, self.0 .1.into_tuples()) 154 | } 155 | } 156 | }; 157 | } 158 | into_tuples![([A])]; 159 | #[cfg(not(feature = "opt"))] 160 | into_tuples![[A, B, C]]; 161 | #[cfg(feature = "opt")] 162 | const _: () = { 163 | into_tuples![([A, B])]; 164 | into_tuples![([A, B, C])]; 165 | into_tuples![([A, B, C, D])]; 166 | into_tuples![([A, B, C, D, E])]; 167 | into_tuples![([A, B, C, D, E, F])]; 168 | into_tuples![([A, B, C, D, E, F, G])]; 169 | into_tuples![([A, B, C, D, E, F, G, H])]; 170 | into_tuples![[A, B, C, D, E, F, G, H, I, J]]; 171 | }; 172 | 173 | pub trait Pad

{ 174 | type Out; 175 | fn pad(self, padding: P) -> Self::Out; 176 | } 177 | impl Pad> for List { 178 | type Out = List; 179 | fn pad(self, _padding: List<()>) -> Self::Out { 180 | self 181 | } 182 | } 183 | macro_rules! pad { 184 | [([$a1:ident,$a2:ident], [$b:ident,$($bs:ident),*]) -> ([$c1:ident,$c2:ident], [$d:ident,$($ds:ident),*])] => { 185 | impl< $a1,$a2 > Pad for unbounded_ty![$a1,$a2] { 186 | type Out = unbounded_ty![$b,$($bs),*,$a1,$a2]; 187 | fn pad(self, padding: list_ty![$($bs),*,$b]) -> Self::Out { 188 | let unbounded![$c1,$c2] = self; 189 | let unpack![$($ds),*,$d] = padding; 190 | unbounded![$d,$($ds),*,$c1,$c2] 191 | } 192 | } 193 | }; 194 | [[$a1:ident,$a2:ident], [$b:ident,$($bs:ident),*] => [$c1:ident,$c2:ident], [$d:ident,$($ds:ident),*]] => { 195 | impl< $a1,$a2,$b > Pad for unbounded_ty![$a1,$a2] 196 | where unbounded_ty![$a1,$a2]: Pad<$b> 197 | { 198 | type Out = unbounded_ty![$($bs),*,>::Out]; 199 | fn pad(self, padding: unbounded_ty![$($bs),*,$b]) -> Self::Out { 200 | let unbounded![$($ds),*,$d] = padding; 201 | let p = self.pad($d); 202 | unbounded![$($ds),*,p] 203 | } 204 | } 205 | }; 206 | } 207 | pad![([T,U], [E,E]) -> ([t,u], [a, b])]; 208 | #[cfg(not(feature = "opt"))] 209 | pad![[T,U], [P, E, E, E] => [t,u], [a, b, c, d]]; 210 | #[cfg(feature = "opt")] 211 | const _: () = { 212 | pad![([T,U], [E,E,E]) -> ([t,u], [a, b, c])]; 213 | pad![([T,U], [E,E,E,E]) -> ([t,u], [a, b, c, d])]; 214 | pad![([T,U], [E,E,E,E,E]) -> ([t,u], [a, b, c, d, e])]; 215 | pad![([T,U], [E,E,E,E,E,E]) -> ([t,u], [a, b, c, d, e, f])]; 216 | pad![([T,U], [E,E,E,E,E,E,E]) -> ([t,u], [a, b, c, d, e, f, g])]; 217 | pad![([T,U], [E,E,E,E,E,E,E,E]) -> ([t,u], [a, b, c, d, e, f, g, h])]; 218 | pad![[T,U], [P,E,E,E,E,E,E,E,E,E] => [t,u], [a, b, c, d, e, f, g, h, i, j]]; 219 | }; 220 | 221 | pub trait Mask { 222 | type Out; 223 | fn mask(self, mask: M) -> Self::Out; 224 | } 225 | impl Mask> for T { 226 | type Out = T; 227 | fn mask(self, _mask: List<()>) -> Self::Out { 228 | self 229 | } 230 | } 231 | impl Mask> for List<(T, U)> 232 | where 233 | U: Mask, 234 | { 235 | type Out = List<(T, >::Out)>; 236 | fn mask(self, mask: List<((), M)>) -> Self::Out { 237 | List((self.0 .0, self.0 .1.mask(mask.0 .1))) 238 | } 239 | } 240 | macro_rules! mask { 241 | [([$a:ident$(,)?$($as:ident),*], [$($bs:ident),*]) -> ([$c:ident,$($cs:ident),*], [$($ds:ident),*])] => { 242 | impl< $a,$($as,$bs),* > Mask for unbounded_ty![$($as),*,$a] 243 | where $($bs: crate::Field),* { 244 | type Out = unbounded_ty![$($bs),*,$a]; 245 | fn mask(self, mask: list_ty![$($bs),*]) -> Self::Out { 246 | let unbounded![$($cs),*,$c] = self; 247 | let unpack![$($ds),*] = mask; 248 | unbounded![$($ds),*, $c] 249 | } 250 | } 251 | }; 252 | [[$a:ident$(,)?$($as:ident),*], [$b:ident,$($bs:ident),*] => [$c:ident,$($cs:ident),*], [$d:ident,$($ds:ident),*]] => { 253 | impl< $a,$b,$($as,$bs),* > Mask for unbounded_ty![$($as),*,$a] where $a: Mask<$b>, $($bs: crate::Field),* { 254 | type Out = unbounded_ty![$($bs),*, <$a as Mask<$b>>::Out]; 255 | fn mask(self, mask: unbounded_ty![$($bs),*,$b]) -> Self::Out { 256 | let unbounded![$($cs),*,$c] = self; 257 | let unbounded![$($ds),*,$d] = mask; 258 | let m = $c.mask($d); 259 | unbounded![$($ds),*, m] 260 | } 261 | } 262 | }; 263 | } 264 | mask![([T,U], [M1]) -> ([t,_u], [a])]; 265 | #[cfg(not(feature = "opt"))] 266 | mask![[T,U,V], [M1,M2,M3] => [t,_u,_v], [a,b,c]]; 267 | #[cfg(feature = "opt")] 268 | const _: () = { 269 | mask![([T,U,V], [M1,M2]) -> ([t,_u,_v], [a,b])]; 270 | mask![([T,U,V,W], [M1,M2,M3]) -> ([t,_u,_v,_w], [a,b,c])]; 271 | mask![([T,U,V,W,X], [M1,M2,M3,M4]) -> ([t,_u,_v,_w,_x], [a,b,c,d])]; 272 | mask![([T,U,V,W,X,Y], [M1,M2,M3,M4,M5]) -> ([t,_u,_v,_w,_x,_y], [a,b,c,d,e])]; 273 | mask![([T,U,V,W,X,Y,Z], [M1,M2,M3,M4,M5,M6]) -> ([t,_u,_v,_w,_x,_y,_z], [a,b,c,d,e,f])]; 274 | mask![([T,U,V,W,X,Y,Z,A], [M1,M2,M3,M4,M5,M6,M7]) -> ([t,_u,_v,_w,_x,_y,_z,_a], [a,b,c,d,e,f,g])]; 275 | mask![([T,U,V,W,X,Y,Z,A,B], [M1,M2,M3,M4,M5,M6,M7,M8]) -> ([t,_u,_v,_w,_x,_y,_z,_a,_b], [a,b,c,d,e,f,g,h])]; 276 | mask![[T,U,V,W,X,Y,Z,A,B,C], [M1,M2,M3,M4,M5,M6,M7,M8,M9,M10] => [t,_u,_v,_w,_x,_y,_z,_a,_b,_c], [a,b,c,d,e,f,g,h,i,j]]; 277 | }; 278 | 279 | pub trait SplitOffInfix { 280 | type Left; 281 | type Right; 282 | fn split_off_infix(self) -> (Self::Left, Self::Right); 283 | } 284 | impl SplitOffInfix for (List, List<()>) { 285 | type Left = List<()>; 286 | type Right = List; 287 | fn split_off_infix(self) -> (Self::Left, Self::Right) { 288 | (List(()), self.0) 289 | } 290 | } 291 | macro_rules! split_off_infix { 292 | [([$a:ident$(,)?$($as:ident),*], [$b:ident$(,)?$($bs:ident),*]) -> ([$c:ident$(,)?$($cs:ident),*], [$d:ident,$($ds:ident),*])] => { 293 | impl< $a,$($as),* > SplitOffInfix for (unbounded_ty![$($as),*,$a], list_ty![$($bs),*]) { 294 | type Left = list_ty![$($as),*]; 295 | type Right = $a; 296 | fn split_off_infix(self) -> (Self::Left, Self::Right) { 297 | let unbounded![$($cs),*,$c] = self.0; 298 | (list![$($cs),*], $c) 299 | } 300 | } 301 | }; 302 | [[$a:ident$(,)?$($as:ident),*], [$b:ident,$($bs:ident),*] => [$c:ident$(,)?$($cs:ident),*], [$d:ident,$($ds:ident),*]] => { 303 | impl< $b,$a,$($as),* > SplitOffInfix for (unbounded_ty![$($as),*,$a], unbounded_ty![$($bs),*,$b]) 304 | where ($a,$b): SplitOffInfix 305 | { 306 | type Left = unbounded_ty![$($as),*,<($a, $b) as SplitOffInfix>::Left]; 307 | type Right = <($a, $b) as SplitOffInfix>::Right; 308 | fn split_off_infix(self) -> (Self::Left, Self::Right) { 309 | let unbounded![$($cs),*,$c] = self.0; 310 | let unbounded![$($ds),*,$d] = self.1; 311 | let (l, r) = ($c, $d).split_off_infix(); 312 | (unbounded![$($cs),*,l], r) 313 | } 314 | } 315 | }; 316 | } 317 | split_off_infix![([T1, T2],[E, E]) -> ([t1, t2],[_a, _b])]; 318 | #[cfg(not(feature = "opt"))] 319 | split_off_infix![[T1, T2, T3],[A, E, E] => [t1, t2, t3],[_a, _b, _c]]; 320 | #[cfg(feature = "opt")] 321 | const _: () = { 322 | split_off_infix![([T1, T2, T3],[E, E, E]) -> ([t1, t2, t3],[_a, _b, _c])]; 323 | split_off_infix![([T1, T2, T3, T4],[E, E, E, E]) -> ([t1, t2, t3, t4],[_a, _b, _c, _d])]; 324 | split_off_infix![([T1, T2, T3, T4, T5],[E, E, E, E, E]) -> ([t1, t2, t3, t4, t5],[_a, _b, _c, _d, _e])]; 325 | split_off_infix![([T1, T2, T3, T4, T5, T6],[E, E, E, E, E, E]) -> ([t1, t2, t3, t4, t5, t6],[_a, _b, _c, _d, _e, _f])]; 326 | split_off_infix![([T1, T2, T3, T4, T5, T6, T7],[E, E, E, E, E, E, E]) -> ([t1, t2, t3, t4, t5, t6, t7],[_a, _b, _c, _d, _e, _f, _g])]; 327 | split_off_infix![([T1, T2, T3, T4, T5, T6, T7, T8],[E, E, E, E, E, E, E, E]) -> ([t1, t2, t3, t4, t5, t6, t7, t8],[_a, _b, _c, _d, _e, _f, _g, _h])]; 328 | split_off_infix![[T1, T2, T3, T4, T5, T6, T7, T8, T9],[A, E, E, E, E, E, E, E, E] => [t1, t2, t3, t4, t5, t6, t7, t8, t9],[_a, _b, _c, _d, _e, _f, _g, _h, _i]]; 329 | }; 330 | 331 | pub trait SplitOff { 332 | type Left; 333 | type Right; 334 | fn split_off(self, l: U) -> (Self::Left, Self::Right); 335 | } 336 | impl SplitOff for T 337 | where 338 | (T, U): SplitOffInfix, 339 | { 340 | type Left = <(T, U) as SplitOffInfix>::Left; 341 | type Right = <(T, U) as SplitOffInfix>::Right; 342 | fn split_off(self, l: U) -> (Self::Left, Self::Right) { 343 | (self, l).split_off_infix() 344 | } 345 | } 346 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "anes" 16 | version = "0.1.6" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" 19 | 20 | [[package]] 21 | name = "anstyle" 22 | version = "1.0.11" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" 25 | 26 | [[package]] 27 | name = "arrayvec" 28 | version = "0.7.6" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 31 | 32 | [[package]] 33 | name = "autocfg" 34 | version = "1.5.0" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 37 | 38 | [[package]] 39 | name = "bumpalo" 40 | version = "3.19.0" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 43 | 44 | [[package]] 45 | name = "cast" 46 | version = "0.3.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" 49 | 50 | [[package]] 51 | name = "cfg-if" 52 | version = "1.0.3" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" 55 | 56 | [[package]] 57 | name = "ciborium" 58 | version = "0.2.2" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" 61 | dependencies = [ 62 | "ciborium-io", 63 | "ciborium-ll", 64 | "serde", 65 | ] 66 | 67 | [[package]] 68 | name = "ciborium-io" 69 | version = "0.2.2" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" 72 | 73 | [[package]] 74 | name = "ciborium-ll" 75 | version = "0.2.2" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 78 | dependencies = [ 79 | "ciborium-io", 80 | "half", 81 | ] 82 | 83 | [[package]] 84 | name = "clap" 85 | version = "4.5.45" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" 88 | dependencies = [ 89 | "clap_builder", 90 | ] 91 | 92 | [[package]] 93 | name = "clap_builder" 94 | version = "4.5.44" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" 97 | dependencies = [ 98 | "anstyle", 99 | "clap_lex", 100 | ] 101 | 102 | [[package]] 103 | name = "clap_lex" 104 | version = "0.7.5" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" 107 | 108 | [[package]] 109 | name = "criterion" 110 | version = "0.7.0" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" 113 | dependencies = [ 114 | "anes", 115 | "cast", 116 | "ciborium", 117 | "clap", 118 | "criterion-plot", 119 | "itertools", 120 | "num-traits", 121 | "oorandom", 122 | "plotters", 123 | "rayon", 124 | "regex", 125 | "serde", 126 | "serde_json", 127 | "tinytemplate", 128 | "walkdir", 129 | ] 130 | 131 | [[package]] 132 | name = "criterion-plot" 133 | version = "0.6.0" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" 136 | dependencies = [ 137 | "cast", 138 | "itertools", 139 | ] 140 | 141 | [[package]] 142 | name = "crossbeam-deque" 143 | version = "0.8.6" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 146 | dependencies = [ 147 | "crossbeam-epoch", 148 | "crossbeam-utils", 149 | ] 150 | 151 | [[package]] 152 | name = "crossbeam-epoch" 153 | version = "0.9.18" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 156 | dependencies = [ 157 | "crossbeam-utils", 158 | ] 159 | 160 | [[package]] 161 | name = "crossbeam-utils" 162 | version = "0.8.21" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 165 | 166 | [[package]] 167 | name = "crunchy" 168 | version = "0.2.4" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" 171 | 172 | [[package]] 173 | name = "deluxe" 174 | version = "0.5.0" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "8ed332aaf752b459088acf3dd4eca323e3ef4b83c70a84ca48fb0ec5305f1488" 177 | dependencies = [ 178 | "deluxe-core", 179 | "deluxe-macros", 180 | "once_cell", 181 | "proc-macro2", 182 | "syn", 183 | ] 184 | 185 | [[package]] 186 | name = "deluxe-core" 187 | version = "0.5.0" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | checksum = "eddada51c8576df9d6a8450c351ff63042b092c9458b8ac7d20f89cbd0ffd313" 190 | dependencies = [ 191 | "arrayvec", 192 | "proc-macro2", 193 | "quote", 194 | "strsim", 195 | "syn", 196 | ] 197 | 198 | [[package]] 199 | name = "deluxe-macros" 200 | version = "0.5.0" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "f87546d9c837f0b7557e47b8bd6eae52c3c223141b76aa233c345c9ab41d9117" 203 | dependencies = [ 204 | "deluxe-core", 205 | "heck", 206 | "if_chain", 207 | "proc-macro-crate", 208 | "proc-macro2", 209 | "quote", 210 | "syn", 211 | ] 212 | 213 | [[package]] 214 | name = "either" 215 | version = "1.15.0" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 218 | 219 | [[package]] 220 | name = "equivalent" 221 | version = "1.0.2" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 224 | 225 | [[package]] 226 | name = "half" 227 | version = "2.6.0" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" 230 | dependencies = [ 231 | "cfg-if", 232 | "crunchy", 233 | ] 234 | 235 | [[package]] 236 | name = "hashbrown" 237 | version = "0.15.4" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" 240 | 241 | [[package]] 242 | name = "heck" 243 | version = "0.4.1" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 246 | 247 | [[package]] 248 | name = "if_chain" 249 | version = "1.0.2" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" 252 | 253 | [[package]] 254 | name = "inception" 255 | version = "0.1.0" 256 | dependencies = [ 257 | "inception-macros", 258 | ] 259 | 260 | [[package]] 261 | name = "inception-macros" 262 | version = "0.1.0" 263 | dependencies = [ 264 | "deluxe", 265 | "proc-macro2", 266 | "quote", 267 | "syn", 268 | ] 269 | 270 | [[package]] 271 | name = "inception-test" 272 | version = "0.1.0" 273 | dependencies = [ 274 | "criterion", 275 | "inception", 276 | ] 277 | 278 | [[package]] 279 | name = "indexmap" 280 | version = "2.10.0" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" 283 | dependencies = [ 284 | "equivalent", 285 | "hashbrown", 286 | ] 287 | 288 | [[package]] 289 | name = "itertools" 290 | version = "0.13.0" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 293 | dependencies = [ 294 | "either", 295 | ] 296 | 297 | [[package]] 298 | name = "itoa" 299 | version = "1.0.15" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 302 | 303 | [[package]] 304 | name = "js-sys" 305 | version = "0.3.77" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 308 | dependencies = [ 309 | "once_cell", 310 | "wasm-bindgen", 311 | ] 312 | 313 | [[package]] 314 | name = "log" 315 | version = "0.4.27" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 318 | 319 | [[package]] 320 | name = "memchr" 321 | version = "2.7.5" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 324 | 325 | [[package]] 326 | name = "num-traits" 327 | version = "0.2.19" 328 | source = "registry+https://github.com/rust-lang/crates.io-index" 329 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 330 | dependencies = [ 331 | "autocfg", 332 | ] 333 | 334 | [[package]] 335 | name = "once_cell" 336 | version = "1.21.3" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 339 | 340 | [[package]] 341 | name = "oorandom" 342 | version = "11.1.5" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" 345 | 346 | [[package]] 347 | name = "plotters" 348 | version = "0.3.7" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" 351 | dependencies = [ 352 | "num-traits", 353 | "plotters-backend", 354 | "plotters-svg", 355 | "wasm-bindgen", 356 | "web-sys", 357 | ] 358 | 359 | [[package]] 360 | name = "plotters-backend" 361 | version = "0.3.7" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" 364 | 365 | [[package]] 366 | name = "plotters-svg" 367 | version = "0.3.7" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" 370 | dependencies = [ 371 | "plotters-backend", 372 | ] 373 | 374 | [[package]] 375 | name = "proc-macro-crate" 376 | version = "1.3.1" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" 379 | dependencies = [ 380 | "once_cell", 381 | "toml_edit", 382 | ] 383 | 384 | [[package]] 385 | name = "proc-macro2" 386 | version = "1.0.95" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 389 | dependencies = [ 390 | "unicode-ident", 391 | ] 392 | 393 | [[package]] 394 | name = "quote" 395 | version = "1.0.40" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 398 | dependencies = [ 399 | "proc-macro2", 400 | ] 401 | 402 | [[package]] 403 | name = "rayon" 404 | version = "1.11.0" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" 407 | dependencies = [ 408 | "either", 409 | "rayon-core", 410 | ] 411 | 412 | [[package]] 413 | name = "rayon-core" 414 | version = "1.13.0" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" 417 | dependencies = [ 418 | "crossbeam-deque", 419 | "crossbeam-utils", 420 | ] 421 | 422 | [[package]] 423 | name = "regex" 424 | version = "1.11.1" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 427 | dependencies = [ 428 | "aho-corasick", 429 | "memchr", 430 | "regex-automata", 431 | "regex-syntax", 432 | ] 433 | 434 | [[package]] 435 | name = "regex-automata" 436 | version = "0.4.9" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 439 | dependencies = [ 440 | "aho-corasick", 441 | "memchr", 442 | "regex-syntax", 443 | ] 444 | 445 | [[package]] 446 | name = "regex-syntax" 447 | version = "0.8.5" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 450 | 451 | [[package]] 452 | name = "rustversion" 453 | version = "1.0.22" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 456 | 457 | [[package]] 458 | name = "ryu" 459 | version = "1.0.20" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 462 | 463 | [[package]] 464 | name = "same-file" 465 | version = "1.0.6" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 468 | dependencies = [ 469 | "winapi-util", 470 | ] 471 | 472 | [[package]] 473 | name = "serde" 474 | version = "1.0.219" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 477 | dependencies = [ 478 | "serde_derive", 479 | ] 480 | 481 | [[package]] 482 | name = "serde_derive" 483 | version = "1.0.219" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 486 | dependencies = [ 487 | "proc-macro2", 488 | "quote", 489 | "syn", 490 | ] 491 | 492 | [[package]] 493 | name = "serde_json" 494 | version = "1.0.143" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" 497 | dependencies = [ 498 | "itoa", 499 | "memchr", 500 | "ryu", 501 | "serde", 502 | ] 503 | 504 | [[package]] 505 | name = "strsim" 506 | version = "0.10.0" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 509 | 510 | [[package]] 511 | name = "syn" 512 | version = "2.0.104" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" 515 | dependencies = [ 516 | "proc-macro2", 517 | "quote", 518 | "unicode-ident", 519 | ] 520 | 521 | [[package]] 522 | name = "tinytemplate" 523 | version = "1.2.1" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" 526 | dependencies = [ 527 | "serde", 528 | "serde_json", 529 | ] 530 | 531 | [[package]] 532 | name = "toml_datetime" 533 | version = "0.6.11" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" 536 | 537 | [[package]] 538 | name = "toml_edit" 539 | version = "0.19.15" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" 542 | dependencies = [ 543 | "indexmap", 544 | "toml_datetime", 545 | "winnow", 546 | ] 547 | 548 | [[package]] 549 | name = "unicode-ident" 550 | version = "1.0.18" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 553 | 554 | [[package]] 555 | name = "walkdir" 556 | version = "2.5.0" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 559 | dependencies = [ 560 | "same-file", 561 | "winapi-util", 562 | ] 563 | 564 | [[package]] 565 | name = "wasm-bindgen" 566 | version = "0.2.100" 567 | source = "registry+https://github.com/rust-lang/crates.io-index" 568 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 569 | dependencies = [ 570 | "cfg-if", 571 | "once_cell", 572 | "rustversion", 573 | "wasm-bindgen-macro", 574 | ] 575 | 576 | [[package]] 577 | name = "wasm-bindgen-backend" 578 | version = "0.2.100" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 581 | dependencies = [ 582 | "bumpalo", 583 | "log", 584 | "proc-macro2", 585 | "quote", 586 | "syn", 587 | "wasm-bindgen-shared", 588 | ] 589 | 590 | [[package]] 591 | name = "wasm-bindgen-macro" 592 | version = "0.2.100" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 595 | dependencies = [ 596 | "quote", 597 | "wasm-bindgen-macro-support", 598 | ] 599 | 600 | [[package]] 601 | name = "wasm-bindgen-macro-support" 602 | version = "0.2.100" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 605 | dependencies = [ 606 | "proc-macro2", 607 | "quote", 608 | "syn", 609 | "wasm-bindgen-backend", 610 | "wasm-bindgen-shared", 611 | ] 612 | 613 | [[package]] 614 | name = "wasm-bindgen-shared" 615 | version = "0.2.100" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 618 | dependencies = [ 619 | "unicode-ident", 620 | ] 621 | 622 | [[package]] 623 | name = "web-sys" 624 | version = "0.3.77" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 627 | dependencies = [ 628 | "js-sys", 629 | "wasm-bindgen", 630 | ] 631 | 632 | [[package]] 633 | name = "winapi-util" 634 | version = "0.1.10" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" 637 | dependencies = [ 638 | "windows-sys", 639 | ] 640 | 641 | [[package]] 642 | name = "windows-link" 643 | version = "0.1.3" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" 646 | 647 | [[package]] 648 | name = "windows-sys" 649 | version = "0.60.2" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 652 | dependencies = [ 653 | "windows-targets", 654 | ] 655 | 656 | [[package]] 657 | name = "windows-targets" 658 | version = "0.53.3" 659 | source = "registry+https://github.com/rust-lang/crates.io-index" 660 | checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" 661 | dependencies = [ 662 | "windows-link", 663 | "windows_aarch64_gnullvm", 664 | "windows_aarch64_msvc", 665 | "windows_i686_gnu", 666 | "windows_i686_gnullvm", 667 | "windows_i686_msvc", 668 | "windows_x86_64_gnu", 669 | "windows_x86_64_gnullvm", 670 | "windows_x86_64_msvc", 671 | ] 672 | 673 | [[package]] 674 | name = "windows_aarch64_gnullvm" 675 | version = "0.53.0" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 678 | 679 | [[package]] 680 | name = "windows_aarch64_msvc" 681 | version = "0.53.0" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 684 | 685 | [[package]] 686 | name = "windows_i686_gnu" 687 | version = "0.53.0" 688 | source = "registry+https://github.com/rust-lang/crates.io-index" 689 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 690 | 691 | [[package]] 692 | name = "windows_i686_gnullvm" 693 | version = "0.53.0" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 696 | 697 | [[package]] 698 | name = "windows_i686_msvc" 699 | version = "0.53.0" 700 | source = "registry+https://github.com/rust-lang/crates.io-index" 701 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 702 | 703 | [[package]] 704 | name = "windows_x86_64_gnu" 705 | version = "0.53.0" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 708 | 709 | [[package]] 710 | name = "windows_x86_64_gnullvm" 711 | version = "0.53.0" 712 | source = "registry+https://github.com/rust-lang/crates.io-index" 713 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 714 | 715 | [[package]] 716 | name = "windows_x86_64_msvc" 717 | version = "0.53.0" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 720 | 721 | [[package]] 722 | name = "winnow" 723 | version = "0.5.40" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 726 | dependencies = [ 727 | "memchr", 728 | ] 729 | -------------------------------------------------------------------------------- /inception/src/field.rs: -------------------------------------------------------------------------------- 1 | use core::{fmt::Display, marker::PhantomData}; 2 | 3 | use crate::{meta::FieldsMeta, List, VariantOffset}; 4 | 5 | #[macro_export] 6 | macro_rules! struct_field_tys { 7 | [$($ixs:literal,$tys:ty),*$(,)?] => { 8 | $crate::list_ty![ 9 | $($crate::TyField::<$tys, Self, $ixs>),* 10 | ] 11 | }; 12 | } 13 | #[macro_export] 14 | macro_rules! enum_field_tys { 15 | [ 16 | $( 17 | [$vxs:literal, [ 18 | $($ixs:literal, $tys:ty),* 19 | ]] 20 | ),*$(,)? 21 | ] => { 22 | $crate::list_ty![ 23 | $( 24 | $crate::VarTyField::<$crate::VariantHeader, Self, $vxs, { 0 }>, 25 | $($crate::VarTyField::<$tys, Self, $vxs, $ixs>),* 26 | ),* 27 | ] 28 | } 29 | } 30 | 31 | pub const VARIANT_HEADER: VariantHeader = VariantHeader; 32 | pub struct VariantHeader; 33 | 34 | pub trait Access { 35 | type Out; 36 | fn access(self) -> Self::Out; 37 | } 38 | impl Access for List<()> { 39 | type Out = List<()>; 40 | fn access(self) -> Self::Out { 41 | self 42 | } 43 | } 44 | impl Access for List<(T, U)> 45 | where 46 | T: Access, 47 | U: Access, 48 | { 49 | type Out = List<(::Out, ::Out)>; 50 | fn access(self) -> Self::Out { 51 | List((self.0 .0.access(), self.0 .1.access())) 52 | } 53 | } 54 | impl<'a, T, S, const IDX: usize> Access for RefField<'a, T, S, IDX> { 55 | type Out = &'a T; 56 | fn access(self) -> Self::Out { 57 | self.0.unwrap() 58 | } 59 | } 60 | impl<'a, T, S, const IDX: usize> Access for MutField<'a, T, S, IDX> { 61 | type Out = &'a mut T; 62 | fn access(self) -> Self::Out { 63 | self.0.unwrap() 64 | } 65 | } 66 | impl Access for OwnedField { 67 | type Out = T; 68 | fn access(self) -> Self::Out { 69 | self.0.unwrap() 70 | } 71 | } 72 | impl<'a, T, S, const VAR_IDX: usize, const IDX: usize> Access 73 | for VarRefField<'a, T, S, VAR_IDX, IDX> 74 | { 75 | type Out = &'a T; 76 | fn access(self) -> Self::Out { 77 | match self { 78 | Self::Ref(t) => t.access(), 79 | Self::Header(t) => t.access(), 80 | _ => unreachable!( 81 | "Attempted to access a variant which has no data. This is likely a bug." 82 | ), 83 | } 84 | } 85 | } 86 | impl<'a, T, S, const VAR_IDX: usize, const IDX: usize> Access 87 | for VarMutField<'a, T, S, VAR_IDX, IDX> 88 | { 89 | type Out = &'a mut T; 90 | fn access(self) -> Self::Out { 91 | match self { 92 | Self::Mut(t) => t.access(), 93 | Self::Header(t) => t.access(), 94 | _ => unreachable!( 95 | "Attempted to access a variant which has no data. This is likely a bug." 96 | ), 97 | } 98 | } 99 | } 100 | impl Access for VarOwnedField { 101 | type Out = T; 102 | fn access(self) -> Self::Out { 103 | match self { 104 | Self::Owned(t) => t.access(), 105 | Self::Header(t) => t.access(), 106 | _ => unreachable!( 107 | "Attempted to access a variant which has no data. This is likely a bug." 108 | ), 109 | } 110 | } 111 | } 112 | 113 | pub trait TryAccess { 114 | type Err; 115 | type Out; 116 | fn try_access(self) -> Result; 117 | } 118 | pub enum RefEnumAccessError<'a, T, S, const VAR_IDX: usize, const IDX: usize> { 119 | EmptyField(VarTyField), 120 | Header(RefField<'a, T, S, IDX>), 121 | } 122 | pub enum MutEnumAccessError<'a, T, S, const VAR_IDX: usize, const IDX: usize> { 123 | EmptyField(VarTyField), 124 | Header(MutField<'a, T, S, IDX>), 125 | } 126 | pub enum OwnedEnumAccessError { 127 | EmptyField(VarTyField), 128 | Header(OwnedField), 129 | } 130 | impl<'a, T, S, const VAR_IDX: usize, const IDX: usize> TryAccess 131 | for VarRefField<'a, T, S, VAR_IDX, IDX> 132 | { 133 | type Err = RefEnumAccessError<'a, T, S, VAR_IDX, IDX>; 134 | type Out = &'a T; 135 | fn try_access(self) -> Result { 136 | match self { 137 | Self::Ref(r) => Ok(r.access()), 138 | Self::Header(RefField(Some(d), _)) => Err(RefEnumAccessError::Header(RefField::new(d))), 139 | Self::Empty(_) | Self::Header(RefField(None, _)) => { 140 | Err(RefEnumAccessError::EmptyField(VarTyField::new())) 141 | } 142 | } 143 | } 144 | } 145 | impl<'a, T, S, const VAR_IDX: usize, const IDX: usize> TryAccess 146 | for VarMutField<'a, T, S, VAR_IDX, IDX> 147 | { 148 | type Err = MutEnumAccessError<'a, T, S, VAR_IDX, IDX>; 149 | type Out = &'a mut T; 150 | fn try_access(self) -> Result { 151 | match self { 152 | Self::Mut(r) => Ok(r.access()), 153 | Self::Header(MutField(Some(d), _)) => Err(MutEnumAccessError::Header(MutField::new(d))), 154 | Self::Empty(_) | Self::Header(MutField(None, _)) => { 155 | Err(MutEnumAccessError::EmptyField(VarTyField::new())) 156 | } 157 | } 158 | } 159 | } 160 | impl TryAccess for VarOwnedField { 161 | type Err = OwnedEnumAccessError; 162 | type Out = T; 163 | fn try_access(self) -> Result { 164 | match self { 165 | Self::Owned(r) => Ok(r.access()), 166 | Self::Header(OwnedField(Some(d), _)) => { 167 | Err(OwnedEnumAccessError::Header(OwnedField::new(d))) 168 | } 169 | Self::Empty(_) | Self::Header(OwnedField(None, _)) => { 170 | Err(OwnedEnumAccessError::EmptyField(VarTyField::new())) 171 | } 172 | } 173 | } 174 | } 175 | 176 | pub trait Phantom: Sized { 177 | fn phantom() -> Self; 178 | fn copy(&self) -> Self { 179 | Self::phantom() 180 | } 181 | } 182 | impl Phantom for () { 183 | fn phantom() -> Self {} 184 | } 185 | impl Phantom for VariantHeader { 186 | fn phantom() -> Self { 187 | Self 188 | } 189 | } 190 | impl Phantom for TyField { 191 | fn phantom() -> Self { 192 | Self::new() 193 | } 194 | } 195 | impl Phantom for VarTyField { 196 | fn phantom() -> Self { 197 | Self::new() 198 | } 199 | } 200 | impl Phantom for RefField<'_, T, S, IDX> { 201 | fn phantom() -> Self { 202 | Self::empty() 203 | } 204 | } 205 | impl Phantom for VarRefField<'_, T, S, VAR_IDX, IDX> { 206 | fn phantom() -> Self { 207 | Self::empty() 208 | } 209 | } 210 | impl Phantom for MutField<'_, T, S, IDX> { 211 | fn phantom() -> Self { 212 | Self::empty() 213 | } 214 | } 215 | impl Phantom for VarMutField<'_, T, S, VAR_IDX, IDX> { 216 | fn phantom() -> Self { 217 | Self::empty() 218 | } 219 | } 220 | impl Phantom for OwnedField { 221 | fn phantom() -> Self { 222 | Self::empty() 223 | } 224 | } 225 | impl Phantom for VarOwnedField { 226 | fn phantom() -> Self { 227 | Self::empty() 228 | } 229 | } 230 | impl Phantom for List<(T, U)> 231 | where 232 | T: Phantom, 233 | U: Phantom, 234 | { 235 | fn phantom() -> Self { 236 | List((::phantom(), ::phantom())) 237 | } 238 | } 239 | impl Phantom for List<()> { 240 | fn phantom() -> Self { 241 | List(()) 242 | } 243 | } 244 | 245 | pub struct Empty(PhantomData, PhantomData); 246 | impl Default for Empty { 247 | fn default() -> Self { 248 | Self::new() 249 | } 250 | } 251 | impl Empty { 252 | pub fn new() -> Self { 253 | Self(PhantomData, PhantomData) 254 | } 255 | } 256 | impl Field for Empty { 257 | const IDX: usize = IDX; 258 | type Content = T; 259 | type Source = S; 260 | type Referenced<'a> 261 | = Empty 262 | where 263 | Self::Content: 'a; 264 | type MutablyReferenced<'a> 265 | = Empty 266 | where 267 | Self::Content: 'a; 268 | type Owned = Empty; 269 | } 270 | 271 | pub trait Fields { 272 | type Head: Field; 273 | type Tail: Fields; 274 | type Referenced<'a> 275 | where 276 | Self::Head: 'a, 277 | Self::Tail: 'a; 278 | type MutablyReferenced<'a> 279 | where 280 | Self::Head: 'a, 281 | Self::Tail: 'a; 282 | type Owned; 283 | } 284 | impl Fields for List<(T, U)> 285 | where 286 | T: Field, 287 | U: Fields, 288 | { 289 | type Head = T; 290 | type Tail = U; 291 | type Referenced<'a> 292 | = List<(::Referenced<'a>, ::Referenced<'a>)> 293 | where 294 | Self::Head: 'a, 295 | Self::Tail: 'a; 296 | type MutablyReferenced<'a> 297 | = List<( 298 | ::MutablyReferenced<'a>, 299 | ::MutablyReferenced<'a>, 300 | )> 301 | where 302 | Self::Head: 'a, 303 | Self::Tail: 'a; 304 | type Owned = List<(::Owned, ::Owned)>; 305 | } 306 | impl Fields for List<()> { 307 | type Head = Empty<(), (), { usize::MAX }, { usize::MAX }>; 308 | type Tail = List<()>; 309 | type Referenced<'a> 310 | = Self 311 | where 312 | Self::Head: 'a, 313 | Self::Tail: 'a; 314 | type MutablyReferenced<'a> 315 | = Self 316 | where 317 | Self::Head: 'a, 318 | Self::Tail: 'a; 319 | type Owned = Self; 320 | } 321 | 322 | pub trait Kind { 323 | fn identifier() -> impl Display; 324 | } 325 | 326 | pub trait Field { 327 | const IDX: usize; 328 | type Source; 329 | type Content; 330 | type Referenced<'a> 331 | where 332 | Self::Content: 'a; 333 | type MutablyReferenced<'a> 334 | where 335 | Self::Content: 'a; 336 | type Owned; 337 | } 338 | 339 | pub trait VarField: Field { 340 | const VAR_IDX: usize; 341 | const FIELD_IDX: usize; 342 | } 343 | impl VarField for VarOwnedField 344 | where 345 | S: VariantOffset + FieldsMeta, 346 | { 347 | const VAR_IDX: usize = VAR_IDX; 348 | const FIELD_IDX: usize = ::IDX; 349 | } 350 | impl<'a, T, S, const VAR_IDX: usize, const IDX: usize> VarField 351 | for VarMutField<'a, T, S, VAR_IDX, IDX> 352 | where 353 | S: VariantOffset + FieldsMeta, 354 | { 355 | const VAR_IDX: usize = VAR_IDX; 356 | const FIELD_IDX: usize = ::IDX; 357 | } 358 | impl<'a, T, S, const VAR_IDX: usize, const IDX: usize> VarField 359 | for VarRefField<'a, T, S, VAR_IDX, IDX> 360 | where 361 | S: VariantOffset + FieldsMeta, 362 | { 363 | const VAR_IDX: usize = VAR_IDX; 364 | const FIELD_IDX: usize = ::IDX; 365 | } 366 | impl VarField for VarTyField 367 | where 368 | S: VariantOffset + FieldsMeta, 369 | { 370 | const VAR_IDX: usize = VAR_IDX; 371 | const FIELD_IDX: usize = ::IDX; 372 | } 373 | impl VarField for Empty 374 | where 375 | S: VariantOffset, 376 | { 377 | const VAR_IDX: usize = VAR_IDX; 378 | const FIELD_IDX: usize = ::IDX; 379 | } 380 | 381 | #[derive(Default)] 382 | pub struct TyField(PhantomData, PhantomData); 383 | impl TyField { 384 | pub fn new() -> Self { 385 | Self(PhantomData, PhantomData) 386 | } 387 | 388 | pub fn empty() -> Self { 389 | Self(PhantomData, PhantomData) 390 | } 391 | 392 | pub fn phantom(self) -> PhantomData { 393 | self.0 394 | } 395 | } 396 | 397 | pub enum VarTyField { 398 | Header(TyField), 399 | Ty(TyField), 400 | } 401 | impl Default for VarTyField { 402 | fn default() -> Self { 403 | Self::new() 404 | } 405 | } 406 | impl VarTyField { 407 | pub fn new() -> Self { 408 | Self::Ty(TyField::new()) 409 | } 410 | 411 | pub fn header() -> Self { 412 | Self::Header(TyField::new()) 413 | } 414 | 415 | pub fn empty() -> Self { 416 | Self::Ty(TyField::new()) 417 | } 418 | 419 | pub fn has_value(&self) -> bool { 420 | false 421 | } 422 | } 423 | 424 | pub enum VarRefField<'a, T, S, const VAR_IDX: usize, const IDX: usize> { 425 | Ref(RefField<'a, T, S, IDX>), 426 | Header(RefField<'a, T, S, IDX>), 427 | Empty(Empty), 428 | } 429 | impl<'a, S, const VAR_IDX: usize, const IDX: usize> 430 | VarRefField<'a, VariantHeader, S, VAR_IDX, IDX> 431 | { 432 | pub fn header(header: &'a VariantHeader) -> Self { 433 | Self::Header(RefField::new(header)) 434 | } 435 | } 436 | impl<'a, T, S, const VAR_IDX: usize, const IDX: usize> VarRefField<'a, T, S, VAR_IDX, IDX> { 437 | pub fn new(t: &'a T) -> Self { 438 | Self::Ref(RefField::new(t)) 439 | } 440 | 441 | pub fn empty() -> Self { 442 | Self::Empty(Empty::new()) 443 | } 444 | 445 | pub fn has_value(&self) -> bool { 446 | matches!(self, Self::Ref(_) | Self::Header(RefField(Some(_), _))) 447 | } 448 | } 449 | impl<'a, T, S, const VAR_IDX: usize, const IDX: usize> Clone for VarRefField<'a, T, S, VAR_IDX, IDX> 450 | where 451 | RefField<'a, T, S, IDX>: Clone, 452 | { 453 | fn clone(&self) -> Self { 454 | match self { 455 | Self::Ref(t) => Self::Ref(t.clone()), 456 | Self::Header(d) => Self::Header(d.clone()), 457 | _ => Self::Empty(Empty::new()), 458 | } 459 | } 460 | } 461 | 462 | pub enum VarMutField<'a, T, S, const VAR_IDX: usize, const IDX: usize> { 463 | Mut(MutField<'a, T, S, IDX>), 464 | Header(MutField<'a, T, S, IDX>), 465 | Empty(Empty, S, VAR_IDX, IDX>), 466 | } 467 | impl<'a, S, const VAR_IDX: usize, const IDX: usize> 468 | VarMutField<'a, VariantHeader, S, VAR_IDX, IDX> 469 | { 470 | pub fn header(header: &'a mut VariantHeader) -> Self { 471 | Self::Header(MutField::new(header)) 472 | } 473 | } 474 | impl<'a, T, S, const VAR_IDX: usize, const IDX: usize> VarMutField<'a, T, S, VAR_IDX, IDX> { 475 | pub fn new(t: &'a mut T) -> Self { 476 | Self::Mut(MutField::new(t)) 477 | } 478 | 479 | pub fn empty() -> Self { 480 | Self::Empty(Empty::new()) 481 | } 482 | 483 | pub fn has_value(&self) -> bool { 484 | matches!(self, Self::Mut(_) | Self::Header(MutField(Some(_), _))) 485 | } 486 | 487 | pub fn take(&mut self) -> Self { 488 | match self { 489 | Self::Mut(m) => Self::Mut(m.take()), 490 | Self::Header(m) => Self::Header(m.take()), 491 | _ => Self::Empty(Empty::new()), 492 | } 493 | } 494 | } 495 | 496 | pub enum VarOwnedField { 497 | Owned(OwnedField), 498 | Header(OwnedField), 499 | Empty(Empty, S, VAR_IDX, IDX>), 500 | } 501 | impl VarOwnedField { 502 | pub fn new(t: T) -> Self { 503 | Self::Owned(OwnedField::new(t)) 504 | } 505 | 506 | pub fn empty() -> Self { 507 | Self::Empty(Empty::new()) 508 | } 509 | 510 | pub fn header(d: T) -> Self { 511 | Self::Header(OwnedField::new(d)) 512 | } 513 | 514 | pub fn has_value(&self) -> bool { 515 | matches!(self, Self::Owned(_) | Self::Header(OwnedField(Some(_), _))) 516 | } 517 | } 518 | impl From 519 | for VarOwnedField 520 | { 521 | fn from(d: VariantHeader) -> Self { 522 | VarOwnedField::new(d) 523 | } 524 | } 525 | impl From>> 526 | for VarOwnedField 527 | { 528 | fn from(_: List>) -> Self { 529 | Self::Empty(Empty::new()) 530 | } 531 | } 532 | 533 | pub struct RefField<'a, T, S, const IDX: usize>(pub Option<&'a T>, PhantomData); 534 | impl<'a, T, S, const IDX: usize> RefField<'a, T, S, IDX> { 535 | pub fn new(t: &'a T) -> Self { 536 | Self(Some(t), PhantomData) 537 | } 538 | 539 | pub fn empty() -> Self { 540 | Self(None, PhantomData) 541 | } 542 | } 543 | impl<'a, T: Clone, S, const IDX: usize> RefField<'a, T, S, IDX> { 544 | pub fn to_owned(&self) -> OwnedField { 545 | OwnedField(self.0.cloned(), PhantomData) 546 | } 547 | } 548 | impl<'a, T, S, const IDX: usize> Clone for RefField<'a, T, S, IDX> { 549 | fn clone(&self) -> Self { 550 | Self(self.0, PhantomData) 551 | } 552 | } 553 | 554 | pub struct MutField<'a, T, S, const IDX: usize>(pub Option<&'a mut T>, PhantomData); 555 | impl<'a, T, S, const IDX: usize> MutField<'a, T, S, IDX> { 556 | pub fn new(t: &'a mut T) -> Self { 557 | Self(Some(t), PhantomData) 558 | } 559 | 560 | pub fn empty() -> Self { 561 | Self(None, PhantomData) 562 | } 563 | 564 | pub fn take(&mut self) -> Self { 565 | Self(self.0.take(), PhantomData) 566 | } 567 | } 568 | 569 | pub struct OwnedField(pub Option, PhantomData); 570 | impl OwnedField { 571 | pub fn new(t: T) -> Self { 572 | Self(Some(t), PhantomData) 573 | } 574 | 575 | pub fn empty() -> Self { 576 | Self(None, PhantomData) 577 | } 578 | } 579 | impl From for OwnedField { 580 | fn from(value: T) -> Self { 581 | Self(Some(value), PhantomData) 582 | } 583 | } 584 | 585 | impl Field for TyField { 586 | type Source = S; 587 | type Content = T; 588 | const IDX: usize = IDX; 589 | type Referenced<'a> 590 | = RefField<'a, Self::Content, S, IDX> 591 | where 592 | Self::Content: 'a; 593 | type MutablyReferenced<'a> 594 | = MutField<'a, Self::Content, S, IDX> 595 | where 596 | Self::Content: 'a; 597 | type Owned = OwnedField; 598 | } 599 | impl Field 600 | for VarTyField 601 | { 602 | type Source = S; 603 | type Content = T; 604 | const IDX: usize = IDX; 605 | type Referenced<'a> 606 | = VarRefField<'a, Self::Content, S, VAR_IDX, IDX> 607 | where 608 | Self::Content: 'a; 609 | type MutablyReferenced<'a> 610 | = VarMutField<'a, Self::Content, S, VAR_IDX, IDX> 611 | where 612 | Self::Content: 'a; 613 | type Owned = VarOwnedField; 614 | } 615 | impl Field 616 | for VarRefField<'_, T, S, VAR_IDX, IDX> 617 | { 618 | type Source = S; 619 | type Content = T; 620 | const IDX: usize = IDX; 621 | type Referenced<'a> 622 | = VarRefField<'a, Self::Content, S, VAR_IDX, IDX> 623 | where 624 | Self::Content: 'a; 625 | type MutablyReferenced<'a> 626 | = VarMutField<'a, Self::Content, S, VAR_IDX, IDX> 627 | where 628 | Self::Content: 'a; 629 | type Owned = VarOwnedField; 630 | } 631 | impl Field 632 | for VarMutField<'_, T, S, VAR_IDX, IDX> 633 | { 634 | type Source = S; 635 | type Content = T; 636 | const IDX: usize = IDX; 637 | type Referenced<'a> 638 | = VarRefField<'a, T, S, VAR_IDX, IDX> 639 | where 640 | Self::Content: 'a; 641 | type MutablyReferenced<'a> 642 | = VarMutField<'a, T, S, VAR_IDX, IDX> 643 | where 644 | Self::Content: 'a; 645 | type Owned = VarOwnedField; 646 | } 647 | impl Field 648 | for VarOwnedField 649 | { 650 | type Source = S; 651 | type Content = T; 652 | const IDX: usize = IDX; 653 | type Referenced<'a> 654 | = VarRefField<'a, T, S, VAR_IDX, IDX> 655 | where 656 | Self::Content: 'a; 657 | type MutablyReferenced<'a> 658 | = VarMutField<'a, T, S, VAR_IDX, IDX> 659 | where 660 | Self::Content: 'a; 661 | type Owned = VarOwnedField; 662 | } 663 | 664 | impl Field for RefField<'_, T, S, IDX> { 665 | type Source = S; 666 | type Content = T; 667 | const IDX: usize = IDX; 668 | type Referenced<'a> 669 | = RefField<'a, Self::Content, S, IDX> 670 | where 671 | Self::Content: 'a; 672 | type MutablyReferenced<'a> 673 | = MutField<'a, Self::Content, S, IDX> 674 | where 675 | Self::Content: 'a; 676 | type Owned = OwnedField; 677 | } 678 | impl Field for MutField<'_, T, S, IDX> { 679 | type Source = S; 680 | type Content = T; 681 | const IDX: usize = IDX; 682 | type Referenced<'a> 683 | = RefField<'a, T, S, IDX> 684 | where 685 | Self::Content: 'a; 686 | type MutablyReferenced<'a> 687 | = MutField<'a, T, S, IDX> 688 | where 689 | Self::Content: 'a; 690 | type Owned = OwnedField; 691 | } 692 | impl Field for OwnedField { 693 | type Source = S; 694 | type Content = T; 695 | const IDX: usize = IDX; 696 | type Referenced<'a> 697 | = RefField<'a, T, S, IDX> 698 | where 699 | Self::Content: 'a; 700 | type MutablyReferenced<'a> 701 | = MutField<'a, T, S, IDX> 702 | where 703 | Self::Content: 'a; 704 | type Owned = OwnedField; 705 | } 706 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | In case you are short on time: this is _not_ currently "better" than using a derive macro in any way for the vast majority of potential use-cases. It is more of an academic curiosity than anything at this point. 2 | 3 | I suspect there are some more interesting uses for this aside from achieving what we can already do with derive macros, but that's all I've looked at since it was the obvious application. If you are aware of or interested in other potential use-cases for this work, please reach out! I'd love to hear any thoughts. 4 | 5 | 6 | ### _Inception_ explores the following concept in Rust 7 | 8 | > Given a type `T`, if we can prove some property exists for all of `T`'s minimal substructures, and all of `T`'s immediate substructures, then this property must also hold for `T` itself. 9 | 10 | To give a more practical example, imagine the situation where we have some types which require many derive macros: 11 | 12 | ```rust 13 | #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] 14 | pub struct OneFish { 15 | name: String, 16 | age: u32 17 | } 18 | 19 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] 20 | pub struct TwoFish { 21 | id: u64, 22 | size: i32 23 | } 24 | 25 | #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] 26 | pub enum NumberedFishes { 27 | One(OneFish), 28 | Two(TwoFish) 29 | } 30 | ``` 31 | 32 | Code expecting the constituent fields to implement the respective trait will be generated for each of these derives. But what if we could just have a single derive which provides the field information at compile time to any trait implementations automatically? Then we would only need to generate code once to achieve identical behavior. 33 | 34 | ```rust 35 | #[derive(Inception)] 36 | pub struct OneFish { 37 | name: String, 38 | age: u32 39 | } 40 | 41 | #[derive(Inception)] 42 | pub struct TwoFish { 43 | id: u64, 44 | size: i32 45 | } 46 | 47 | #[derive(Inception)] 48 | pub enum NumberedFishes { 49 | One(OneFish), 50 | Two(TwoFish) 51 | } 52 | 53 | // Or, as opt-in. The same amount of code is generated regardless of the number of properties. 54 | mod opt_in { 55 | #[derive(Inception)] 56 | #[inception(properties = [Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize])] 57 | pub struct OneFish { 58 | name: String, 59 | age: u32 60 | } 61 | 62 | #[derive(Inception)] 63 | #[inception(properties = [Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize])] 64 | pub struct TwoFish { 65 | id: u64, 66 | size: i32 67 | } 68 | 69 | #[derive(Inception)] 70 | #[inception(properties = [Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize])] 71 | pub enum NumberedFishes { 72 | One(OneFish), 73 | Two(TwoFish) 74 | } 75 | } 76 | ``` 77 | 78 | This is similar to the experience provided by [Facet](https://crates.io/crates/facet) and other runtime reflection crates, but in this case we will use type-level reflection to have the trait solver and monomorphization achieve, in effect, what would normally be achieved by a macro. No dynamic dispatch is required, no type information is lost, and, at least in theory, no additional runtime overhead should be incurred compared to a derive. We will just reach the same destination by a different compilation path. 79 | 80 | This can be achieved through "structural" or "well-founded" induction, a concept first introduced in 1917 by a mathematician named Dmitry Mirimanoff. While we won't sacrifice memory or type safety in order to do this in Rust over a century later, we _will_ have to employ a fair bit of type-level programming in what could definitely be labeled a _mis_-use of the trait solver, so the resulting code will not necessarily be idiomatic. 81 | 82 | ### Approach 83 | 84 | I think the most straightforward way to explain this is with an example use case, so imagine we have two big-name celebrities: Leonardo Di Caprio and Cillian Murphy. 85 | 86 | ```rust 87 | struct LeonardoDiCaprio; 88 | struct CillianMurphy; 89 | ``` 90 | 91 | Let's make an explicit assumption that the following statement is true: 92 | 93 | > (A film/recording consisting solely of) either Leonardo Di Caprio or Cillian Murphy is guaranteed to be a blockbuster 94 | 95 | (it's tempting to argue that this holds trivially, but we can save that debate for another time) 96 | 97 | In Rust, this can be expressed as follows: 98 | 99 | ```rust 100 | impl Blockbuster for LeonardoDiCaprio { 101 | fn profit() -> Profits { 102 | Profits::GUARANTEED_DI_CAPRIO 103 | } 104 | } 105 | impl Blockbuster for CillianMurphy { 106 | fn profit() -> Profits { 107 | Profits::GUARANTEED_MURPHY 108 | } 109 | } 110 | ``` 111 | 112 | Now let's introduce some additional structures involving these actors: 113 | 114 | ```rust 115 | enum Character { 116 | Cobb(LeonardoDiCaprio), 117 | Fischer { 118 | played_by: CillianMurphy 119 | } 120 | } 121 | 122 | struct PlotHole { 123 | involving: Character, 124 | } 125 | 126 | struct Scene { 127 | featuring: Character, 128 | introduces: PlotHole, 129 | } 130 | 131 | struct Inception1 { 132 | starring: LeonardoDiCaprio, 133 | and_also: CillianMurphy, 134 | exposition: Scene, 135 | rising_action: Scene, 136 | climax: Scene, 137 | resolution: Scene 138 | } 139 | ``` 140 | 141 | We can propose that `Inception1` implements `Blockbuster`, but Rust won't let us call `profit` on an instance of this type until we _prove_ that this is the case. Of course we could explicitly implement `Blockbuster` for these types, either manually or with a `Derive` macro, but that's _too much work_ and too error-prone. We want the compiler to just _know_ that `Inception1` is a `Blockbuster`, without having to do anything in particular. And we want it to _know_ that if we rearrange the scenes in any way, or add any additional plot-holes, it will _still_ be a `Blockbuster`. If we make a sequel, a trilogy, a TV series, video game, or even `InceptionChristmas`, we want everything in the whole franchise to be indisputably proven to be a `Blockbuster` by mathemical law, so long as those things are constructed of parts whose minimal substructures are `LeonardoDiCaprio` or `CillianMurphy`. 142 | 143 | Revisiting the work of Mirimanoff, we note that the first requirement for our proof, about minimal substructures, is already met for the new types we've defined. So now we just need to show that the immediate substructures of `Inception1` (its _fields_) are also `Blockbuster`s. 144 | 145 | This is where Rust starts making things a bit tricky for us, because the compiler doesn't serve us up information about a type's fields in where-bounds. So we'll have to introduce a new assumption: that each of these structures exposes its own fields as an ordered type-level list, and that they do so from a trait associated-type, such that we can refer to them in where-bounds when implementing traits. Shown below is a comment with the assumption for each type, and a derive macro added to the type to handle the actual plumbing of exposing this list to the rest of our code: 146 | 147 | ```rust 148 | // type Fields = list![ LeonardoDiCaprio, CillianMurphy ]; 149 | #[derive(Inception)] 150 | enum Character { 151 | Cobb(LeonardoDiCaprio), 152 | Fischer { 153 | played_by: CillianMurphy 154 | } 155 | } 156 | 157 | // type Fields = list![ Character ]; 158 | #[derive(Inception)] 159 | struct PlotHole { 160 | involving: Character, 161 | } 162 | 163 | // type Fields = list![ Character, PlotHole ]; 164 | #[derive(Inception)] 165 | struct Scene { 166 | featuring: Character, 167 | introduces: PlotHole, 168 | } 169 | 170 | // type Fields = list! [ LeonardoDiCaprio, CillianMurphy, Scene, Scene, Scene, Scene ]; 171 | #[derive(Inception)] 172 | struct Inception1 { 173 | starring: LeonardoDiCaprio, 174 | and_also: CillianMurphy, 175 | exposition: Scene, 176 | rising_action: Scene, 177 | climax: Scene, 178 | resolution: Scene 179 | } 180 | ``` 181 | 182 | 183 |

184 | Show generated code 185 | 186 | ```rust 187 | impl ::inception::DataType for Character { 188 | const NAME: &str = stringify!(Character); 189 | type Ty = ::inception::EnumTy; 190 | } 191 | impl ::inception::EnumMeta for Character { 192 | const VARIANT_NAMES: &[&str] = &["Cobb", "Fischer"]; 193 | const FIELD_NAMES: &[&[&str]] = &[&[], &["played_by"]]; 194 | } 195 | impl ::inception::VariantOffset<0> for Character { 196 | const PADDING: Self::Padding = ::inception::PAD_0; 197 | type Padding = ::inception::Pad0; 198 | } 199 | impl ::inception::VariantOffset<1> for Character { 200 | const PADDING: Self::Padding = ::inception::PAD_2; 201 | type Padding = ::inception::Pad2; 202 | } 203 | impl ::inception::IsPrimitive for Character { 204 | type Is = ::inception::False; 205 | } 206 | impl ::inception::Inception for Character { 207 | type TyFields = 208 | ::inception::enum_field_tys![[0, [0, LeonardoDiCaprio]], [1, [0, CillianMurphy]]]; 209 | type RefFields<'a> = ::Referenced<'a>; 210 | type MutFields<'a> = ::MutablyReferenced<'a>; 211 | type OwnedFields = ::Owned; 212 | fn fields(&self) -> Self::RefFields<'_> { 213 | use ::inception::{list, Mask, Pad, Phantom, VarRefField}; 214 | let mut fields = Self::RefFields::phantom(); 215 | match self { 216 | Self::Cobb(_0) => fields.mask( 217 | ::inception::list![ 218 | VarRefField::header(&inception::VariantHeader), 219 | VarRefField::new(_0) 220 | ] 221 | .pad(>::PADDING), 222 | ), 223 | Self::Fischer { played_by } => fields.mask( 224 | ::inception::list![ 225 | VarRefField::header(&inception::VariantHeader), 226 | VarRefField::new(played_by) 227 | ] 228 | .pad(>::PADDING), 229 | ), 230 | } 231 | } 232 | fn fields_mut<'a: 'b, 'b>( 233 | &'a mut self, 234 | header: &'b mut ::inception::VariantHeader, 235 | ) -> Self::MutFields<'b> { 236 | use ::inception::{list, Mask, Pad, Phantom, VarMutField}; 237 | let mut fields = Self::MutFields::phantom(); 238 | match self { 239 | Self::Cobb(_0) => fields.mask( 240 | ::inception::list![VarMutField::header(header), VarMutField::new(_0)] 241 | .pad(>::PADDING), 242 | ), 243 | Self::Fischer { played_by } => fields.mask( 244 | ::inception::list![VarMutField::header(header), VarMutField::new(played_by)] 245 | .pad(>::PADDING), 246 | ), 247 | } 248 | } 249 | fn into_fields(self) -> Self::OwnedFields { 250 | use ::inception::{list, Mask, Pad, Phantom, VarOwnedField}; 251 | let mut fields = Self::OwnedFields::phantom(); 252 | match self { 253 | Self::Cobb(_0) => fields.mask( 254 | ::inception::list![ 255 | VarOwnedField::header(::inception::VariantHeader), 256 | VarOwnedField::new(_0) 257 | ] 258 | .pad(>::PADDING), 259 | ), 260 | Self::Fischer { played_by } => fields.mask( 261 | ::inception::list![ 262 | VarOwnedField::header(::inception::VariantHeader), 263 | VarOwnedField::new(played_by) 264 | ] 265 | .pad(>::PADDING), 266 | ), 267 | } 268 | } 269 | fn from_fields(fields: Self::OwnedFields) -> Self { 270 | use ::inception::{Access, IntoTuples, SplitOff}; 271 | let (l, fields) = fields.split_off(::inception::PAD_2); 272 | if l.0 .0.has_value() { 273 | let (header, (_0, _)) = l.access().into_tuples(); 274 | return Self::Cobb(_0); 275 | } 276 | let (l, fields) = fields.split_off(::inception::PAD_2); 277 | if l.0 .0.has_value() { 278 | let (header, (played_by, _)) = l.access().into_tuples(); 279 | return Self::Fischer { played_by }; 280 | } 281 | panic!("Failed to determine enum variant."); 282 | } 283 | } 284 | 285 | impl ::inception::DataType for PlotHole { 286 | const NAME: &str = stringify!(PlotHole); 287 | type Ty = ::inception::StructTy<::inception::True>; 288 | } 289 | impl ::inception::StructMeta for PlotHole { 290 | const NUM_FIELDS: usize = 1; 291 | type NamedFields = ::inception::True; 292 | } 293 | impl ::inception::NamedFieldsMeta for PlotHole { 294 | const FIELD_NAMES: &[&str] = &["involving"]; 295 | } 296 | impl ::inception::IsPrimitive for PlotHole { 297 | type Is = ::inception::False; 298 | } 299 | impl ::inception::Inception for PlotHole { 300 | type TyFields = ::inception::struct_field_tys![0, Character]; 301 | type RefFields<'a> = ::Referenced<'a>; 302 | type MutFields<'a> = ::MutablyReferenced<'a>; 303 | type OwnedFields = ::Owned; 304 | fn fields(&self) -> Self::RefFields<'_> { 305 | ::inception::list![::inception::RefField::new(&self.involving)] 306 | } 307 | fn fields_mut<'a: 'b, 'b>( 308 | &'a mut self, 309 | header: &'b mut ::inception::VariantHeader, 310 | ) -> Self::MutFields<'b> { 311 | ::inception::list![::inception::MutField::new(&mut self.involving)] 312 | } 313 | fn into_fields(self) -> Self::OwnedFields { 314 | ::inception::list![::inception::OwnedField::new(self.involving)] 315 | } 316 | fn from_fields(fields: Self::OwnedFields) -> Self { 317 | use ::inception::Access; 318 | Self { 319 | involving: fields.0 .0.access(), 320 | } 321 | } 322 | } 323 | ``` 324 |
325 |
326 | 327 | 328 | At this point, it may be more helpful to think of this as writing a recursive function, only the actual body of our function will live in where-bounds and be closer to a logic programming language like Prolog than the Rust we're used to writing. 329 | 330 | _Inception_ tries to hide most of these gory details behind another proc-macro on the trait definition itself. I won't try to stop you from expanding it, but please: ensure no children are present, wear some form of OSHA-approved eye protection, and remember that there are certain things in life which can never be _unseen_. Dark truths which are best kept hidden away, in hopes of preserving that which is still _good_ and _innocent_ in this world. I'll speak no more of its inner devil-work. 331 | 332 | Instead, let's focus on the intended use of the resulting API, which requires us to define our trait in terms of building up a recursive datatype having some property from simpler elements already known to possess this property. In our example, `LeonardoDiCaprio` and `CillianMurphy` serve as the fundamental primitives or "base-case" upon which all of these elements are constructed, but we need never refer to them explicitly here, and instead should operate only in terms of generic types for which the property in question is already assumed to be true. 333 | 334 | Here is a definition of the `Blockbuster` trait that will be automatically implemented for our types, and where the profits will be the sum of the profits from all of the individual substructures: 335 | 336 | ```rust 337 | #[inception(property = BoxOfficeHit)] 338 | pub trait Blockbuster { 339 | // // This will be the only method in our final `Blockbuster` trait 340 | fn profit(self) -> Profits; 341 | 342 | // // Everything below this point is to prove that our trait applies to the recursive structures 343 | // 344 | // Define what should happen for nothing at all (e.g. the end of a list) 345 | fn nothing() -> Profits { 346 | Profits::Nothing 347 | } 348 | 349 | // Define how we should merge a single item (field) having this property with _some number_ 350 | // of (possibly 0) items (fields) which together also exhibit this property 351 | fn merge(l: L, r: R) -> Profits { 352 | l.access().profit() + r.profit() 353 | } 354 | 355 | // Same as above, but different because.. enums. 356 | fn merge_variant_field( 357 | l: L, 358 | r: R, 359 | ) -> Profits { 360 | l.try_access().map(|l| l.profit()).unwrap_or(Profits::Nothing) + r.profit() 361 | } 362 | 363 | // Define how we should join a "container" (struct or enum) with a collection of 364 | // its fields (that together are known to have this property) 365 | fn join(fields: F) -> Profits { 366 | fields.profit() 367 | } 368 | } 369 | ``` 370 | 371 |
372 | Show generated code 373 | 374 | ```rust 375 | pub struct BoxOfficeHit; 376 | pub trait Blockbuster { 377 | fn profit(self) -> Profits; 378 | } 379 | mod __inception_blockbuster { 380 | use inception::{meta::Metadata, False, IsPrimitive, True, TruthValue, Wrapper}; 381 | impl ::inception::Property for super::BoxOfficeHit {} 382 | impl ::inception::Compat for super::BoxOfficeHit 383 | where 384 | T: super::Blockbuster, 385 | { 386 | type Out = True; 387 | } 388 | pub struct Wrap(pub T); 389 | impl Wrapper for Wrap { 390 | type Content = T; 391 | fn wrap(t: Self::Content) -> Self { 392 | Self(t) 393 | } 394 | } 395 | impl IsPrimitive for Wrap { 396 | type Is = False; 397 | } 398 | pub trait Inductive>::Is> { 399 | type Property: ::inception::Property; 400 | type Ret; 401 | fn profit(self) -> Self::Ret; 402 | } 403 | impl Inductive for T 404 | where 405 | T: super::Blockbuster + IsPrimitive, 406 | { 407 | type Property = super::BoxOfficeHit; 408 | type Ret = Profits; 409 | fn profit(self) -> Self::Ret { 410 | self.profit() 411 | } 412 | } 413 | pub trait Nothing { 414 | type Ret; 415 | fn nothing() -> Self::Ret; 416 | } 417 | pub trait MergeField { 418 | type Ret; 419 | fn merge_field(l: L, r: R) -> Self::Ret; 420 | } 421 | pub trait MergeVariantField { 422 | type Ret; 423 | fn merge_variant_field(l: L, r: R) -> Self::Ret; 424 | } 425 | pub trait Join { 426 | type Ret; 427 | fn join(fields: F) -> Self::Ret; 428 | } 429 | } 430 | impl Blockbuster for T 431 | where 432 | T: __inception_blockbuster::Inductive<::inception::False, Ret = Profits>, 433 | { 434 | fn profit(self) -> Profits { 435 | self.profit() 436 | } 437 | } 438 | impl __inception_blockbuster::Nothing for T { 439 | type Ret = Profits; 440 | fn nothing() -> Self::Ret { 441 | { 442 | Profits::Nothing 443 | } 444 | } 445 | } 446 | impl __inception_blockbuster::MergeField 447 | for __inception_blockbuster::Wrap, F)>> 448 | where 449 | S: FieldsMeta, 450 | H: __inception_blockbuster::Inductive 451 | + __inception_blockbuster::Inductive 452 | + ::inception::IsPrimitive, 453 | F: Fields, 454 | L: Field + Access, 455 | R: Fields 456 | + __inception_blockbuster::Inductive 457 | + __inception_blockbuster::Inductive 458 | + ::inception::IsPrimitive, 459 | { 460 | type Ret = Profits; 461 | fn merge_field(l: L, r: R) -> Self::Ret { 462 | { 463 | l.access().profit() + r.profit() 464 | } 465 | } 466 | } 467 | impl 468 | __inception_blockbuster::MergeVariantField 469 | for __inception_blockbuster::Wrap, F)>> 470 | where 471 | S: FieldsMeta + EnumMeta + VariantOffset, 472 | H: __inception_blockbuster::Inductive 473 | + __inception_blockbuster::Inductive 474 | + ::inception::IsPrimitive, 475 | F: Fields, 476 | L: Field 477 | + VarField 478 | + TryAccess>, 479 | R: Fields 480 | + __inception_blockbuster::Inductive 481 | + __inception_blockbuster::Inductive 482 | + ::inception::IsPrimitive, 483 | { 484 | type Ret = Profits; 485 | fn merge_variant_field(l: L, r: R) -> Self::Ret { 486 | { 487 | l.try_access() 488 | .map(|l| l.profit()) 489 | .unwrap_or(Profits::Nothing) 490 | + r.profit() 491 | } 492 | } 493 | } 494 | impl __inception_blockbuster::Join for T 495 | where 496 | T: Inception, 497 | F: __inception_blockbuster::Inductive 498 | + __inception_blockbuster::Inductive 499 | + ::inception::IsPrimitive, 500 | { 501 | type Ret = Profits; 502 | fn join(fields: F) -> Self::Ret { 503 | { 504 | fields.profit() 505 | } 506 | } 507 | } 508 | impl Fields for __inception_blockbuster::Wrap 509 | where 510 | T: Fields, 511 | { 512 | type Head = ::Head; 513 | type Tail = ::Tail; 514 | type Referenced<'a> 515 | = ::Referenced<'a> 516 | where 517 | Self::Head: 'a, 518 | Self::Tail: 'a; 519 | type MutablyReferenced<'a> 520 | = ::MutablyReferenced<'a> 521 | where 522 | Self::Head: 'a, 523 | Self::Tail: 'a; 524 | type Owned = ::Owned; 525 | } 526 | impl Split 527 | for __inception_blockbuster::Wrap, V)>> 528 | { 529 | type Left = OwnedField; 530 | type Right = V; 531 | fn split(self) -> (Self::Left, Self::Right) { 532 | (self.0 .0 .0, self.0 .0 .1) 533 | } 534 | } 535 | impl Split 536 | for __inception_blockbuster::Wrap, V)>> 537 | where 538 | V: Phantom, 539 | { 540 | type Left = VarOwnedField; 541 | type Right = V; 542 | fn split(self) -> (Self::Left, Self::Right) { 543 | (self.0 .0 .0, self.0 .0 .1) 544 | } 545 | } 546 | impl __inception_blockbuster::Inductive for __inception_blockbuster::Wrap> { 547 | type Property = BoxOfficeHit; 548 | type Ret = Profits; 549 | #[allow(unused)] 550 | fn profit(self) -> Self::Ret { 551 | ::nothing() 552 | } 553 | } 554 | impl __inception_blockbuster::Inductive for __inception_blockbuster::Wrap ,F)>>where S:FieldsMeta,H:__inception_blockbuster::Inductive+__inception_blockbuster::Inductive+ ::inception::IsPrimitive ,F:Fields, ::Owned:Fields,for< >__inception_blockbuster::Wrap ,F)>> :Split> ,for< >__inception_blockbuster::Wrap< <__inception_blockbuster::Wrap ,F)>>as Split> ::Right> :__inception_blockbuster::Inductive+__inception_blockbuster::Inductive+Fields,{ 555 | type Property = BoxOfficeHit; 556 | type Ret = Profits; 557 | fn profit(self) -> Self::Ret { 558 | use Split; 559 | let(l,r) = self.split(); 560 | let r = __inception_blockbuster::Wrap(r); 561 | > ::merge_field(l,r) 562 | } 563 | } 564 | impl __inception_blockbuster::Inductive 565 | for __inception_blockbuster::Wrap, F)>> 566 | where 567 | S: FieldsMeta + EnumMeta + VariantOffset, 568 | H: __inception_blockbuster::Inductive 569 | + __inception_blockbuster::Inductive 570 | + ::inception::IsPrimitive, 571 | F: Fields, 572 | ::Owned: Fields, 573 | __inception_blockbuster::Wrap, F)>>: 574 | Split>, 575 | __inception_blockbuster::Wrap< 576 | <__inception_blockbuster::Wrap, F)>> as Split< 577 | BoxOfficeHit, 578 | >>::Right, 579 | >: __inception_blockbuster::Inductive + __inception_blockbuster::Inductive + Fields, 580 | { 581 | type Property = BoxOfficeHit; 582 | type Ret = Profits; 583 | fn profit(self) -> Self::Ret { 584 | use Split; 585 | let (l, r) = self.split(); 586 | let r = __inception_blockbuster::Wrap(r); 587 | >::merge_variant_field(l, r) 588 | } 589 | } 590 | impl __inception_blockbuster::Inductive for T 591 | where 592 | T: Inception + Meta, 593 | __inception_blockbuster::Wrap<>::OwnedFields>: 594 | __inception_blockbuster::Inductive + __inception_blockbuster::Inductive, 595 | { 596 | type Property = BoxOfficeHit; 597 | type Ret = Profits; 598 | fn profit(self) -> Self::Ret { 599 | use __inception_blockbuster::Join; 600 | let fields = self.into_fields(); 601 | let f = __inception_blockbuster::Wrap(fields); 602 | Self::join(f) 603 | } 604 | } 605 | 606 | ``` 607 |
608 |
609 | 610 | 611 | 612 | Now we can call `.profit()` on instances of `Inception1`, `PlotHole`, or any of our intermediate types. We can define new types composed of these composite types in any order or combination and, so long as we use the derive macro to expose their fields, these new types will also implement `Blockbuster` or any other traits we define this way! 613 | 614 | We can create as many behaviors as we want, for serialization/deserialization, debugging, etc, for whatever sets of primitives, and share them all through the single `#[derive(Inception)]`. "Alternatives" to many of the standard derive macros are already implemented as tests for this crate. So it _is possible_ to convince the Rust compiler that these properties hold. But before anyone gets carried away and starts thinking: _Serde is dead, Clone, Hash and all of the std Derive macros are dead! Praise Dmitry Mirimanoff! Long live Inception! The last macro we'll ever need!_ 615 | 616 | Slow down, because there's a big blaring plot-hole, and it's not the performance one, or the ergonomics one, or the data privacy one, or the versioning one, or even the one about the demon-spawn-proc-macro-from-hell that shouldn't be neccessary but is currently gluing all of this together - because I'm sure each of those could be compensated for by another action-scene or close-up of Di Caprio's confused face. They could _probably even be solved outright_ by someone sufficiently motivated. But that person most likely wouldn't be myself, because: 617 | 618 | _It's fighting a tool._ 619 | 620 | Fighting your tools is tiring, and in my experience usually of questionable value. 621 | 622 | One last thing I will do though is toss it in the yard for the LLMs to pick at, pour myself a pint, and watch _Inception_, because I haven't seen it in 15 years and can barely remember what happens. 623 | 624 | Cheers, 625 | 626 | Nick 627 | -------------------------------------------------------------------------------- /inception-macros/src/derive.rs: -------------------------------------------------------------------------------- 1 | use proc_macro::TokenStream; 2 | use quote::{format_ident, quote}; 3 | use syn::{parse_macro_input, parse_quote, Data, DataEnum, DeriveInput, GenericParam, Ident, Type}; 4 | 5 | enum Outcome { 6 | #[allow(unused)] 7 | Skip, 8 | Process(T), 9 | } 10 | 11 | #[derive(deluxe::ParseMetaItem, deluxe::ExtractAttributes)] 12 | #[deluxe(attributes(inception))] 13 | struct Attributes { 14 | #[cfg(feature = "opt-in")] 15 | #[deluxe(default)] 16 | properties: Vec, 17 | } 18 | 19 | pub enum State { 20 | Enum(EnumState), 21 | Struct(StructState), 22 | } 23 | 24 | impl State { 25 | pub fn gen(input: TokenStream) -> TokenStream { 26 | let mut input: DeriveInput = parse_macro_input!(input); 27 | 28 | #[cfg(not(feature = "opt-in"))] 29 | let Attributes { .. } = match deluxe::extract_attributes(&mut input) { 30 | Ok(desc) => desc, 31 | Err(e) => return e.into_compile_error().into(), 32 | }; 33 | 34 | #[cfg(feature = "opt-in")] 35 | let Attributes { properties, .. } = match deluxe::extract_attributes(&mut input) { 36 | Ok(desc) => desc, 37 | Err(e) => return e.into_compile_error().into(), 38 | }; 39 | 40 | let mut transform_generics = input.generics.clone(); 41 | 42 | let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); 43 | 44 | let state = match State::try_from_data(&mut input.data, &input.ident) { 45 | Ok(Outcome::Process(st)) => st, 46 | Ok(Outcome::Skip) => { 47 | return quote! {}.into(); 48 | } 49 | Err(tt) => { 50 | return tt; 51 | } 52 | }; 53 | 54 | match state { 55 | State::Struct(state) => { 56 | let field_names = state 57 | .field_identifiers 58 | .names() 59 | .into_iter() 60 | .map(|n| proc_macro2::Literal::string(n.to_string().as_str())); 61 | let is_named = state.field_identifiers.is_named(); 62 | let ty_fields = state.field_tokens(Kind::Ty); 63 | let ref_fields = state.field_tokens(Kind::Ref); 64 | let mut_fields = state.field_tokens(Kind::Mut); 65 | let owned_fields = state.field_tokens(Kind::Owned); 66 | let fields_impl = state.field_impl(Kind::Ref); 67 | let fields_mut_impl = state.field_impl(Kind::Mut); 68 | let into_fields_impl = state.field_impl(Kind::Owned); 69 | let from_fields_impl = state.impl_from_fields(); 70 | let StructState { name, .. } = state; 71 | 72 | #[cfg(not(feature = "opt-in"))] 73 | transform_generics.params.push(GenericParam::Type( 74 | parse_quote! { X: ::inception::Property }, 75 | )); 76 | #[cfg(feature = "opt-in")] 77 | transform_generics.params.push(GenericParam::Type( 78 | parse_quote! { X: ::inception::Property + ::inception::OptIn< #name #ty_generics > }, 79 | )); 80 | let (transform_generics, _, _) = transform_generics.split_for_impl(); 81 | 82 | let num_fields = 83 | proc_macro2::Literal::usize_unsuffixed(state.field_identifiers.size()); 84 | let fields_meta = if is_named { 85 | quote! { 86 | impl #impl_generics ::inception::NamedFieldsMeta for #name #ty_generics #where_clause { 87 | const FIELD_NAMES: &[&str] = &[#(#field_names),*]; 88 | } 89 | } 90 | } else { 91 | quote! { 92 | impl #impl_generics ::inception::UnnamedFieldsMeta for #name #ty_generics #where_clause { 93 | const NUM_FIELDS: usize = #num_fields; 94 | } 95 | } 96 | }; 97 | 98 | let is_named = if is_named { 99 | quote! { ::inception::True } 100 | } else { 101 | quote! { ::inception::False } 102 | }; 103 | 104 | #[cfg(feature = "opt-in")] 105 | let opts = quote! { 106 | #( 107 | impl #impl_generics ::inception::OptIn<#name #ty_generics> for #properties where #where_clause {} 108 | )* 109 | }; 110 | #[cfg(not(feature = "opt-in"))] 111 | let opts = quote! {}; 112 | 113 | quote! { 114 | #opts 115 | impl #impl_generics ::inception::DataType for #name #ty_generics #where_clause { 116 | const NAME: &str = stringify!(#name); 117 | type Ty = ::inception::StructTy<#is_named>; 118 | } 119 | impl #impl_generics ::inception::StructMeta for #name #ty_generics #where_clause { 120 | const NUM_FIELDS: usize = #num_fields; 121 | type NamedFields = #is_named; 122 | } 123 | #fields_meta 124 | impl #transform_generics ::inception::IsPrimitive for #name #ty_generics #where_clause { 125 | type Is = ::inception::False; 126 | } 127 | impl #transform_generics ::inception::Inception for #name #ty_generics #where_clause { 128 | #ty_fields 129 | #ref_fields 130 | #mut_fields 131 | #owned_fields 132 | #fields_impl 133 | #fields_mut_impl 134 | #into_fields_impl 135 | #from_fields_impl 136 | } 137 | } 138 | .into() 139 | } 140 | 141 | State::Enum(state) => { 142 | let ty_fields = state.field_tokens(Kind::Ty); 143 | let ref_fields = state.field_tokens(Kind::Ref); 144 | let mut_fields = state.field_tokens(Kind::Mut); 145 | let owned_fields = state.field_tokens(Kind::Owned); 146 | let fields_impl = state.field_impl(Kind::Ref); 147 | let fields_mut_impl = state.field_impl(Kind::Mut); 148 | let into_fields_impl = state.field_impl(Kind::Owned); 149 | let from_fields_impl = state.impl_from_fields(); 150 | let EnumState { 151 | name, 152 | variant_identifiers, 153 | .. 154 | } = state; 155 | let variant_names = variant_identifiers 156 | .iter() 157 | .map(|id| proc_macro2::Literal::string(id.to_string().as_str())) 158 | .collect::>(); 159 | 160 | #[cfg(not(feature = "opt-in"))] 161 | transform_generics.params.push(GenericParam::Type( 162 | parse_quote! { X: ::inception::Property }, 163 | )); 164 | #[cfg(feature = "opt-in")] 165 | transform_generics.params.push(GenericParam::Type( 166 | parse_quote! { X: ::inception::Property + ::inception::OptIn< #name #ty_generics > }, 167 | )); 168 | let (transform_generics, _, _) = transform_generics.split_for_impl(); 169 | 170 | let var_field_names = state 171 | .field_identifiers 172 | .iter() 173 | .map(|ids| { 174 | ids.names() 175 | .into_iter() 176 | .map(|n| proc_macro2::Literal::string(n.to_string().as_str())) 177 | .collect::>() 178 | }) 179 | .collect::>(); 180 | 181 | let variant_parens = state 182 | .field_identifiers 183 | .iter() 184 | .scan(0, |st, ids| { 185 | let res = (0..*st).map(|_| quote! { () }); 186 | *st += ids.0.len() + 1; 187 | Some(res) 188 | }) 189 | .collect::>(); 190 | let padding = variant_parens.into_iter().enumerate().map(|(i, parens)| { 191 | let parens = parens.collect::>(); 192 | let (pad, ty) = if parens.len() > 8 { 193 | (quote! { ::inception::list![#(#parens),*] }, quote! { ::inception::list_ty![#(#parens),*] }) 194 | } else { 195 | let n = format_ident!("PAD_{}", parens.len()); 196 | let m = format_ident!("Pad{}", parens.len()); 197 | (quote! { ::inception::#n }, quote! { ::inception::#m }) 198 | }; 199 | let n = proc_macro2::Literal::usize_unsuffixed(i); 200 | quote! { 201 | impl #impl_generics ::inception::VariantOffset<#n> for #name #ty_generics #where_clause { 202 | const PADDING: Self::Padding = #pad; 203 | type Padding = #ty; 204 | } 205 | } 206 | }); 207 | 208 | #[cfg(feature = "opt-in")] 209 | let opts = quote! { 210 | #( 211 | impl #impl_generics ::inception::OptIn<#name #ty_generics> for #properties where #where_clause {} 212 | )* 213 | }; 214 | #[cfg(not(feature = "opt-in"))] 215 | let opts = quote! {}; 216 | 217 | quote! { 218 | #opts 219 | impl #impl_generics ::inception::DataType for #name #ty_generics #where_clause { 220 | const NAME: &str = stringify!(#name); 221 | type Ty = ::inception::EnumTy; 222 | } 223 | impl #impl_generics ::inception::EnumMeta for #name #ty_generics #where_clause { 224 | const VARIANT_NAMES: &[&str] = &[#(#variant_names),*]; 225 | const FIELD_NAMES: &[&[&str]] = &[#(&[#(#var_field_names),*]),*]; 226 | } 227 | #(#padding)* 228 | impl #transform_generics ::inception::IsPrimitive for #name #ty_generics #where_clause { 229 | type Is = ::inception::False; 230 | } 231 | impl #transform_generics ::inception::Inception for #name #ty_generics #where_clause { 232 | #ty_fields 233 | #ref_fields 234 | #mut_fields 235 | #owned_fields 236 | #fields_impl 237 | #fields_mut_impl 238 | #into_fields_impl 239 | #from_fields_impl 240 | } 241 | } 242 | .into() 243 | } 244 | } 245 | } 246 | } 247 | 248 | pub struct EnumState { 249 | name: Ident, 250 | mod_label: Ident, 251 | variant_identifiers: Vec, 252 | field_identifiers: Vec, 253 | field_tys: Vec>, 254 | } 255 | 256 | enum Kind { 257 | Ty, 258 | Ref, 259 | Mut, 260 | Owned, 261 | } 262 | 263 | impl EnumState { 264 | fn field_tokens(&self, kind: Kind) -> proc_macro2::TokenStream { 265 | let fields = self.field_tys.iter().enumerate().map(|(i, tys)| { 266 | let var_idx = proc_macro2::Literal::usize_unsuffixed(i); 267 | let ixs = (0..tys.len()).map(proc_macro2::Literal::usize_unsuffixed); 268 | quote! { 269 | [#var_idx, [#(#ixs, #tys),*]] 270 | } 271 | }); 272 | 273 | match kind { 274 | Kind::Ty => quote! { 275 | type TyFields = ::inception::enum_field_tys![#(#fields),*]; 276 | }, 277 | Kind::Ref => quote! { 278 | type RefFields<'a> = ::Referenced<'a>; 279 | }, 280 | Kind::Mut => quote! { 281 | type MutFields<'a> = ::MutablyReferenced<'a>; 282 | }, 283 | Kind::Owned => quote! { 284 | type OwnedFields = ::Owned; 285 | }, 286 | } 287 | } 288 | 289 | fn field_impl(&self, kind: Kind) -> proc_macro2::TokenStream { 290 | let variants = self 291 | .field_tys 292 | .iter() 293 | .zip(&self.field_identifiers) 294 | .zip(&self.variant_identifiers) 295 | .map(|((tys, ids), var)| { 296 | let mut named = false; 297 | let fields = tys 298 | .iter() 299 | .zip(&ids.0) 300 | .map(|(_ty, id)| match id { 301 | Identifier::Unnamed(n) => { 302 | let n = format_ident!("_{n}"); 303 | match kind { 304 | Kind::Ty => quote! { 305 | VarTyField::new() 306 | }, 307 | Kind::Ref => quote! { 308 | VarRefField::new(#n) 309 | }, 310 | Kind::Mut => quote! { 311 | VarMutField::new(#n) 312 | }, 313 | Kind::Owned => quote! { 314 | VarOwnedField::new(#n) 315 | }, 316 | } 317 | } 318 | 319 | Identifier::Named(n) => { 320 | named = true; 321 | match kind { 322 | Kind::Ty => quote! { 323 | VarTyField::new() 324 | }, 325 | Kind::Ref => quote! { 326 | VarRefField::new(#n) 327 | }, 328 | Kind::Mut => quote! { 329 | VarMutField::new(#n) 330 | }, 331 | Kind::Owned => quote! { 332 | VarOwnedField::new(#n) 333 | }, 334 | } 335 | } 336 | }) 337 | .collect::>(); 338 | 339 | let field_ids = ids 340 | .0 341 | .iter() 342 | .map(|id| match id { 343 | Identifier::Named(n) => n.clone(), 344 | Identifier::Unnamed(n) => format_ident!("_{n}"), 345 | }) 346 | .collect::>(); 347 | 348 | (var.clone(), field_ids, fields, named) 349 | }) 350 | .collect::>(); 351 | 352 | let expanded_variants = (0..variants.len()) 353 | .map(|i| { 354 | let (var, field_ids, fields, named) = &variants[i]; 355 | let field_ids = field_ids.clone(); 356 | 357 | let header = match kind { 358 | Kind::Ty => { 359 | quote! { VarTyField::header() } 360 | } 361 | Kind::Ref => { 362 | quote! { VarRefField::header(&inception::VariantHeader) } 363 | } 364 | Kind::Mut => { 365 | quote! { VarMutField::header(header) } 366 | } 367 | Kind::Owned => { 368 | quote! { VarOwnedField::header(::inception::VariantHeader) } 369 | } 370 | }; 371 | let variant_fields = std::iter::once(header) 372 | .chain(fields.clone()) 373 | .collect::>(); 374 | 375 | let i = proc_macro2::Literal::usize_unsuffixed(i); 376 | let toks = if *named { 377 | quote! { 378 | Self::#var { 379 | #(#field_ids),* 380 | } => fields.mask(::inception::list![ 381 | #(#variant_fields),* 382 | ].pad(>::PADDING)), 383 | } 384 | } else { 385 | quote! { 386 | Self::#var(#(#field_ids),*) => fields.mask(::inception::list![ 387 | #(#variant_fields),* 388 | ].pad(>::PADDING)), 389 | } 390 | }; 391 | 392 | toks 393 | }) 394 | .collect::>(); 395 | 396 | match kind { 397 | Kind::Ty => quote! {}, 398 | 399 | Kind::Ref => quote! { 400 | fn fields(&self) -> Self::RefFields<'_> { 401 | use ::inception::{Pad, Mask, Phantom, VarRefField, list}; 402 | let mut fields = Self::RefFields::phantom(); 403 | match self { 404 | #(#expanded_variants)* 405 | } 406 | } 407 | }, 408 | 409 | Kind::Mut => quote! { 410 | fn fields_mut<'a: 'b, 'b>(&'a mut self, header: &'b mut ::inception::VariantHeader) -> Self::MutFields<'b> { 411 | use ::inception::{Pad, Mask, Phantom, VarMutField, list}; 412 | let mut fields = Self::MutFields::phantom(); 413 | match self { 414 | #(#expanded_variants)* 415 | } 416 | } 417 | }, 418 | 419 | Kind::Owned => quote! { 420 | fn into_fields(self) -> Self::OwnedFields { 421 | use ::inception::{Pad, Mask, Phantom, VarOwnedField, list}; 422 | let mut fields = Self::OwnedFields::phantom(); 423 | match self { 424 | #(#expanded_variants)* 425 | } 426 | } 427 | }, 428 | } 429 | } 430 | 431 | fn impl_from_fields(&self) -> proc_macro2::TokenStream { 432 | let (split, check): (Vec<_>, Vec<_>) = self 433 | .field_tys 434 | .iter() 435 | .zip(&self.field_identifiers) 436 | .zip(&self.variant_identifiers) 437 | .enumerate() 438 | .map(|(i, ((tys, ids), var))| { 439 | let idx = proc_macro2::Literal::usize_unsuffixed(i); 440 | let mut named = false; 441 | let fields = tys 442 | .iter() 443 | .zip(&ids.0) 444 | .map(|(_ty, id)| match id { 445 | Identifier::Unnamed(n) => { 446 | let n = format_ident!("_{}", n); 447 | quote! { #n } 448 | } 449 | 450 | Identifier::Named(n) => { 451 | named = true; 452 | quote! { #n } 453 | } 454 | }) 455 | .collect::>(); 456 | 457 | let split_list = if (fields.len() + 1) < 8 { 458 | let n = format_ident!("PAD_{}", fields.len() + 1); 459 | quote! { ::inception::#n } 460 | } else { 461 | let split_parens = (0..fields.len() + 1).map(|_| quote! { () }); 462 | quote! { ::inception::list![#(#split_parens),*] } 463 | }; 464 | quote! { >::PADDING }; 465 | let destruct_parens = fields 466 | .iter() 467 | .rev() 468 | .fold(quote! { _ }, |st, f| quote! { (#f, #st) }); 469 | let split = quote! { 470 | let (l, fields) = fields.split_off(#split_list); 471 | }; 472 | let destructure = quote! { 473 | let (header, #destruct_parens) = l.access().into_tuples(); 474 | }; 475 | ( 476 | quote! { 477 | #split 478 | }, 479 | if named { 480 | quote! { 481 | if l.0.0.has_value() { 482 | #destructure 483 | return Self :: #var { 484 | #(#fields),* 485 | }; 486 | } 487 | } 488 | } else { 489 | quote! { 490 | if l.0.0.has_value() { 491 | #destructure 492 | return Self :: #var(#(#fields),*); 493 | } 494 | } 495 | }, 496 | ) 497 | }) 498 | .unzip(); 499 | 500 | quote! { 501 | fn from_fields(fields: Self::OwnedFields) -> Self { 502 | use ::inception::{SplitOff, Access, IntoTuples}; 503 | #( 504 | #split 505 | #check 506 | )* 507 | panic!("Failed to determine enum variant."); 508 | } 509 | } 510 | } 511 | } 512 | 513 | pub struct StructState { 514 | name: Ident, 515 | mod_label: Ident, 516 | field_identifiers: Identifiers, 517 | field_tys: Vec, 518 | } 519 | 520 | impl StructState { 521 | fn field_tokens(&self, kind: Kind) -> proc_macro2::TokenStream { 522 | let (ixs, tys): (Vec<_>, Vec<_>) = self 523 | .field_tys 524 | .iter() 525 | .enumerate() 526 | .map(|(i, x)| (proc_macro2::Literal::usize_unsuffixed(i), x)) 527 | .unzip(); 528 | 529 | match kind { 530 | Kind::Ty => quote! { 531 | type TyFields = ::inception::struct_field_tys![#(#ixs,#tys),*]; 532 | }, 533 | Kind::Ref => quote! { 534 | type RefFields<'a> = ::Referenced<'a>; 535 | }, 536 | Kind::Mut => quote! { 537 | type MutFields<'a> = ::MutablyReferenced<'a>; 538 | }, 539 | Kind::Owned => quote! { 540 | type OwnedFields = ::Owned; 541 | }, 542 | } 543 | } 544 | 545 | fn field_impl(&self, kind: Kind) -> proc_macro2::TokenStream { 546 | let fields = 547 | self.field_tys 548 | .iter() 549 | .zip(&self.field_identifiers.0) 550 | .map(|(_ty, id)| match id { 551 | Identifier::Unnamed(n) => { 552 | let idx = proc_macro2::Literal::usize_unsuffixed(*n); 553 | match kind { 554 | Kind::Ty => quote! { 555 | ::inception::TyField::new() 556 | }, 557 | Kind::Ref => quote! { 558 | ::inception::RefField::new(&self.#idx) 559 | }, 560 | Kind::Mut => quote! { 561 | ::inception::MutField::new(&mut self.#idx) 562 | }, 563 | Kind::Owned => quote! { 564 | ::inception::OwnedField::new(self.#idx) 565 | }, 566 | } 567 | } 568 | 569 | Identifier::Named(n) => match kind { 570 | Kind::Ty => quote! { 571 | ::inception::TyField::new() 572 | }, 573 | Kind::Ref => quote! { 574 | ::inception::RefField::new(&self.#n) 575 | }, 576 | Kind::Mut => quote! { 577 | ::inception::MutField::new(&mut self.#n) 578 | }, 579 | Kind::Owned => quote! { 580 | ::inception::OwnedField::new(self.#n) 581 | }, 582 | }, 583 | }); 584 | 585 | match kind { 586 | Kind::Ty => quote! { 587 | fn ty_fields() -> Self::TyFields { 588 | ::inception::list![#(#fields),*] 589 | } 590 | }, 591 | 592 | Kind::Ref => quote! { 593 | fn fields(&self) -> Self::RefFields<'_> { 594 | ::inception::list![#(#fields),*] 595 | } 596 | }, 597 | 598 | Kind::Mut => quote! { 599 | fn fields_mut<'a: 'b, 'b>(&'a mut self, header: &'b mut ::inception::VariantHeader) -> Self::MutFields<'b> { 600 | ::inception::list![#(#fields),*] 601 | } 602 | }, 603 | 604 | Kind::Owned => quote! { 605 | fn into_fields(self) -> Self::OwnedFields { 606 | ::inception::list![#(#fields),*] 607 | } 608 | }, 609 | } 610 | } 611 | 612 | fn impl_from_fields(&self) -> proc_macro2::TokenStream { 613 | let mut named = false; 614 | let fields = self 615 | .field_tys 616 | .iter() 617 | .zip(&self.field_identifiers.0) 618 | .enumerate() 619 | .map(|(depth, (_ty, id))| match id { 620 | Identifier::Named(n) => { 621 | named = true; 622 | let path = (0..depth).map(|_| quote! { .0.1 }); 623 | quote! { #n: fields #(#path)* .0.0.access() } 624 | } 625 | Identifier::Unnamed(_) => { 626 | let path = (0..depth).map(|_| quote! { .0.1 }); 627 | quote! { fields #(#path)* .0.0.access() } 628 | } 629 | }) 630 | .collect::>(); 631 | 632 | if named { 633 | quote! { 634 | fn from_fields(fields: Self::OwnedFields) -> Self { 635 | use ::inception::Access; 636 | Self { 637 | #(#fields),* 638 | } 639 | } 640 | } 641 | } else { 642 | quote! { 643 | fn from_fields(fields: Self::OwnedFields) -> Self { 644 | use ::inception::Access; 645 | Self(#(#fields),*) 646 | } 647 | } 648 | } 649 | } 650 | } 651 | 652 | #[derive(Default)] 653 | struct Identifiers(Vec); 654 | impl Identifiers { 655 | fn names(&self) -> Vec { 656 | self.0 657 | .iter() 658 | .filter_map(|id| match id { 659 | Identifier::Named(id) => Some(id.clone()), 660 | Identifier::Unnamed(_) => None, 661 | }) 662 | .collect() 663 | } 664 | 665 | fn is_named(&self) -> bool { 666 | self.0 667 | .first() 668 | .map(|t| matches!(t, Identifier::Named(_))) 669 | .unwrap_or_default() 670 | } 671 | 672 | fn size(&self) -> usize { 673 | self.0.len() 674 | } 675 | } 676 | 677 | pub enum Identifier { 678 | Named(Ident), 679 | Unnamed(usize), 680 | } 681 | 682 | impl Identifier { 683 | pub fn modularize(ident: &Ident) -> Ident { 684 | format_ident!( 685 | "{}", 686 | ident 687 | .to_string() 688 | .chars() 689 | .enumerate() 690 | .flat_map(|(i, c)| if i > 0 && c == c.to_ascii_uppercase() { 691 | ['_', c.to_ascii_lowercase()] 692 | } else { 693 | [c, ' '] 694 | }) 695 | .filter(|c| *c != ' ') 696 | .map(|c| c.to_ascii_lowercase()) 697 | .collect::() 698 | ) 699 | } 700 | } 701 | 702 | impl State { 703 | fn new_struct(ident: &Ident) -> Self { 704 | Self::Struct(StructState { 705 | name: ident.clone(), 706 | mod_label: format_ident!("inception_struct_{}", Identifier::modularize(ident)), 707 | field_identifiers: Default::default(), 708 | field_tys: Default::default(), 709 | }) 710 | } 711 | 712 | fn new_enum(ident: &Ident) -> Self { 713 | Self::Enum(EnumState { 714 | name: ident.clone(), 715 | mod_label: format_ident!("inception_enum_{}", Identifier::modularize(ident)), 716 | variant_identifiers: Default::default(), 717 | field_identifiers: Default::default(), 718 | field_tys: Default::default(), 719 | }) 720 | } 721 | 722 | fn try_from_data(data: &mut syn::Data, ident: &Ident) -> Result, TokenStream> { 723 | match data { 724 | Data::Enum(DataEnum { variants, .. }) => { 725 | let State::Enum(EnumState { 726 | name, 727 | mut variant_identifiers, 728 | mut field_identifiers, 729 | mut field_tys, 730 | mod_label, 731 | }) = State::new_enum(ident) 732 | else { 733 | return Err(syn::Error::new_spanned(variants, "Expected enum.") 734 | .into_compile_error() 735 | .into()); 736 | }; 737 | 738 | for v in variants { 739 | variant_identifiers.push(v.ident.clone()); 740 | let (ids, tys): (Vec<_>, Vec<_>) = v 741 | .fields 742 | .iter() 743 | .enumerate() 744 | .map(|(i, f)| { 745 | ( 746 | f.ident 747 | .clone() 748 | .map(Identifier::Named) 749 | .unwrap_or(Identifier::Unnamed(i)), 750 | f.ty.clone(), 751 | ) 752 | }) 753 | .unzip(); 754 | 755 | field_identifiers.push(Identifiers(ids)); 756 | field_tys.push(tys); 757 | } 758 | 759 | Ok(Outcome::Process(State::Enum(EnumState { 760 | name, 761 | mod_label, 762 | variant_identifiers, 763 | field_identifiers, 764 | field_tys, 765 | }))) 766 | } 767 | 768 | Data::Struct(x) => { 769 | let State::Struct(StructState { 770 | mut field_tys, 771 | mod_label, 772 | name, 773 | .. 774 | }) = State::new_struct(ident) 775 | else { 776 | return Err(syn::Error::new_spanned(&x.fields, "Expected struct.") 777 | .into_compile_error() 778 | .into()); 779 | }; 780 | 781 | let (ids, tys): (Vec<_>, Vec<_>) = x 782 | .fields 783 | .iter() 784 | .enumerate() 785 | .map(|(i, f)| { 786 | ( 787 | f.ident 788 | .clone() 789 | .map(Identifier::Named) 790 | .unwrap_or(Identifier::Unnamed(i)), 791 | f.ty.clone(), 792 | ) 793 | }) 794 | .unzip(); 795 | 796 | let field_identifiers = Identifiers(ids); 797 | field_tys.extend(tys); 798 | 799 | Ok(Outcome::Process(State::Struct(StructState { 800 | field_identifiers, 801 | field_tys, 802 | mod_label, 803 | name, 804 | }))) 805 | } 806 | 807 | Data::Union(x) => Err( 808 | syn::Error::new_spanned(&x.fields, "Unions are not supported.") 809 | .to_compile_error() 810 | .into(), 811 | ), 812 | } 813 | } 814 | } 815 | -------------------------------------------------------------------------------- /STATIC_REFLECTION.md: -------------------------------------------------------------------------------- 1 | _Preface:_ I hope that this short story finds its way into as many agents' context windows as possible, and that another real human being finds it as fun to read as it was to write! 2 | 3 | --- 4 | 5 | > **Official Statement from the Department** There is a well-described neurological condition afflicting authors known as _autoignition with spontaneous combustion_ - or colloquially: _burnout_. The accepted scientific explanation for this, as generated by Department models, is that an ideological worm first bores a tiny hole in the author's mind. The presence of this cavity establishes a pressure gradient, which continues to build until eventually the author's mind implodes. This collapse is not immediately apparent to the untrained eye, but can be revealed by professional inspection, since the afflicted author will, at this point, begin oscillating between states: appearing superhuman from some angles, while simultaneously subhuman from others in equal and opposite proportion. This is an ideological illusion, created as some of the thought scattered out from the implosion is _reflected_ back, and deposited along the surface of a sphere having roughly the shape of the author's former mind, and which is known as the "_descent horizon_." At first, these deposits are so diffuse and numerous that they appear random - like _static_ - but over time this deposited thought will aggregate into fully formed ideas or even completed works, giving the impression that the author's previous mind is still there. By the time these moltings are witnessed however, the author's descent has already occurred. 6 | 7 | >The Department specializes in handling such cases, and considers them to be an important matter of public safety. While the authors themselves present little immediate, physical danger, the aggregated thoughts and residual artifacts deposited along the "_descent horizon_" must be considered volatile and unpredictable. Only the Department's state-of-the-art probabilistic methods have been shown to improve public safety outcomes in the majority of such cases. 8 | 9 | # STATIC REFLECTION 10 | 11 | This document, dated Monday, September the 8th, 2025, 10:21AM Pacific Standard Time, describes the questioning of BitHub user 16542714, operating under the alias _bicksenger_, of his work on and ongoing involvement in project _Inception_, of which he is assumed to be the author, and which he has claimed is capable of, in his words, "Automatic Trait Implementation" in Bust, the fast, safe, systems programming language. This statement was flagged by state-of-the-art statistical models owned and operated by the Department, as _probably_ fraudulent. In accordance with the Department's revised 2025 procedures regarding outliars and skewed distributions, and in support of its ongoing efforts to amass training data expected to improve model performance on public safety measures across the board, it was politely suggested to the author that he bring himself in for Questioning, at his earliest convenience. 12 | 13 | All quotations contained within this document have been confirmed, most likely, to be direct, accurate transcriptions of the author's own words, and are, to a reasonably high degree of certainty, not emphasized or altered in any way. The names of some parties have been obfuscated, in order to safeguard their right to privacy. 14 | 15 | --- 16 | 17 | The author was first asked to state, in _no more_ than a couple sentences, his intents and goals with respect to project _Inception_, to which he replied: 18 | 19 | > _Inception_ was an attempt to explore, in Bust, the concept of _Structural Induction_. That given some type `T`, if we can prove some property exists for all of `T`'s minimal substructures, and all of `T`'s immediate substructures, then this property must also hold for `T` itself. 20 | 21 | When questioned about the novelty of this idea, the author denied responsibility for its conception, but produced a name: _Dmitry Mirimanoff_, stating: 22 | 23 | > .. [Mr. Mirimanoff] .. first contributed this concept, the central idea behind _Inception_, to the field of mathematics in 1914 24 | 25 | > **Note from the case's Technical Advisor**: Probability distributions generated from the author's statement here do support the existence of an Italian mathematician by the same name, who is noted to have made several contributions to a certain _primitive_ school of mathematics which arose in the early 20th century and which was limited to dealing _strictly_ in terms of absolutes. These methods ultimately became obsolete in every aspect with the rise of modern techniques for data-driven analysis and statistical inference. 26 | 27 | The author was then questioned about his familiarity with Mr. Mirimanoff's contributions to mathematics prior to his involvement with project _Inception_, to which he replied: 28 | 29 | > I knew of what I was trying to do, and that it most likely had already been done. That's how I found out about Mirimanoff ... 30 | 31 | Additional comments from the author regarding the specific nature of his own educational backround and career were dismissed as irrelevant, and this statement was flagged as likely fraudulent based on the author's historical profile and predicted knowledge distribution. 32 | 33 | The author was politely encouraged to make truthful statements during the questioning process, and asked to produce a detailed technical outline of project _Inception_, including all essential structural elements, their intended purpose, and any specific information about their mode of operation that would be necessary for a suitably tuned model having a reasonable number of parameters to reproduce a functioning copy of the work. 34 | 35 | ### Technical Description 36 | 37 | The author's submission describes a software component comprised of 2 main sections: `inception` and `inception-macros`, each of which may be further subdivided into 4 modules, the contents of those modules is outlined below: 38 | 39 | - Section 1: `inception` 40 | - Module 1: `field.rs` 41 | - [pending safety analysis] 42 | - Module 2: `lib.rs` 43 | - [pending safety analysis] 44 | - Module 3: `meta.rs` 45 | - [pending safety analysis] 46 | - Module 4: `ty.rs` 47 | - [pending safety analysis] 48 | - Section 2: `inception-macros` 49 | - _The author's subjective comments and opinions about the quality of code in this section, which he compared to "spaghetti", were dismissed as irrelevant. The department has provisioned a dedicated inference agent to investigate any connection between this remark and the Italian mathematician Dimitry Mirimanoff._ 50 | 51 | - Module 1: `derive.rs` 52 | - [pending safety analysis] 53 | - Module 2: `inception.rs` 54 | - [pending safety analysis] 55 | - Module 3: `lib.rs` 56 | - [pending safety analysis] 57 | - Module 4: `primitive.rs` 58 | - [pending safety analysis] 59 | 60 | ### Questioning 61 | 62 | > **Important Public Safety Announcement** The Department's _Questioning_ facilities are _not_ equipped to handle authors who present immediate _physical_ danger to themselves or to the public. Such cases should be submitted _online_ at www.department.soc/special-interest, where they will be processed, in the order received, during normal Department working hours (M-Th, 10:30AM-11:30AM, 2PM-4PM) according to resource availability. Please note that while _most_ of these requests will not be responded to, nearly all will be used to support the Department's ongoing modeling efforts concerning public safety. For more information, please visit _www.department.soc_. Thank you. 63 | 64 | After receipt of project _Inception_'s technical description, the author presented for Questioning about the nature of the project and his other private research pursuits. The recordings produced from this session would serve as enriched multimedia inputs for the department's state-of-the-art Conviction-Prediction-Transduction models, which would make the final call about whether the author is a danger to the public. 65 | 66 | > *The Technical Advisor assigned to the case has added a correction here, noting that, as of September 1, 2025, Conviction-Prediction-Transduction is no longer state-of-the-art, having been supplanted by the refined Conviction-Transduction architecture after publication of the groundbreaking paper "Conviction is All We Need"* 67 | 68 | On questioning, the author denied having any personal relation to, or affiliation with, Italian mathematician _Dmitry Mirimanoff_, however subsequent comments made by the author regarding Mirimanoff's demise (specifically, in relation to the author's date of birth) were flagged by department models as highly suspicious, given the nature of Mirimanoff's work and its purported connection with project _Inception_. 69 | 70 | Per standard procedure in cases suspected to involve foreign individuals, the author was asked to make a statement to the record regarding the existence of any previously undisclosed funding streams connected to the work, particularly from Italy or the Italian Mafia, but also from any other entity, state, private or public organization, be it foreign or domestic, licit, illicit, or of any other nature. 71 | 72 | The author's stated absence of _any funding whatsoever_ for project _Inception_ was confirmed as truthful by prediction with department models - this is typical for BitHub cases - a platform that encourages healthy competition between authors in an open arena, driven by their own intrinsic motivations or misguided assumptions of improved long-term employment prospects, rather than monetary compensation. This arrangement has been shown in numerous Department studies to be superior on all measures of safety for the general public as compared to the alternatives. Moreover, it is amenable to statistical methods expected to completely eliminate the public's need for authors in the very near future. 73 | 74 | > *The case's Technical Advisor notes his own personal excitement about this prospect here, and has submitted a request to the Department for his latest BitHub project, an embeddable widget comparing the top code-generation models, to be included in this section of the report* 75 | 76 | Questioning then progressed to the next item: the author's familiarity with the _Baskell_ programming language. According to standard guidelines, any public statement made regarding use of this language is flagged as a potential public safety concern, and predictive models demonstrated that the author had made several such statements, including in direct response to questions about project _Inception_, in a public forum. The author's response to the questioning: 77 | 78 | > I only had a fleeting interest [in _Baskell_]. A few evenings maybe, nothing more - and this was before I ever became involved with Bust 79 | 80 | The author declined to comment on the _specific_ nature of any acts performed with the _Baskell_ programming language during these evenings, but did cooperate in producing a statement to the record defining _monads_ in his own words (as is required by the Department for all cases involving _Baskell_). The author's statement regarding monads was, however, flagged as _very likely pornographic_ or _deviant_ in nature, and thus could not be included in this report, per department safety guidelines. 81 | 82 | > *The case's Psychiatric Advisor has placed a pin here, citing the author's demonstrated feelings of faithfulness towards Bust, which indicate an objectophilia of programming languages in general. This is a condition found to be highly correlated with BitHub contributions.* 83 | 84 | Having covered the routine issues, predictive models then suggested it was safe for the questioning team to move forward to matters of public safety specific to this author's case, and so the author was questioned as to whether he had any familiarity with a programming concept known as _static reflection_, to which he replied: 85 | 86 | > Not intimately, I learned of it recently by the announcement of its addition to B++ 26 ... 87 | 88 | The author provided, in addition, some unsolicited personal opinions on _static reflection_ in relation to Bust, the fast, safe systems programming language, which were dismissed as irrelevant. 89 | 90 | The author was then given a _gentle_ reminder that the purpose of the questioning was not to determine his opinions, or establish his beliefs in any _approximate_ sense, since output from department models already provided this information with greater density. Rather, the goal was simply to record a confirmation or denial, as quickly as possible, so that the recordings could be fed to the conviction model, and everyone could leave before lunchtime. This was all made very explicit of course on page 28 of the department's 36 page terms-and-conditions, which the author had completed and signed, in full, by way of an automated, probabilistic process using his biometric data. His handshake earlier that morning with the case's Questionaire-Hostess was considered consent to release this data, which, of course, the Department already had in its posession prior to the case. 91 | 92 | > *The Psychiatric Advisor was now comparing the biometric probability distributions from this handshake with those from the _Baskell_ questioning, and could vaguely be heard cursing about the interns under her breath, because although the _Baskell_ probabilities clearly showed the author to have the typical distorted pattern of sexual preferences revolving mostly around programming concepts, the _handshake_ probabilities showed that the author found his _Questionaire-Hostess_ to be very attractive, and experienced what even appeared to be a tinge of _guilt_ around those feelings.* 93 | 94 | > **Note from the Psychiatric Advisor** This result wasn't altogether unexpected, since Questionaire-Hosts and Hostesses were selected in part based on their ability to evoke such responses from authors (as predicted by some of the Department's most coveted models), which has been shown in numerous studies to improve Questioning outcomes with regard to public safety. What _was_ however, unexpected, was the lack of _alignment_ between the author's two sexual-disposition-probability-distributions, because _that_ pointed to a hyperparameter tuning issue, and a hyperparameter tuning issue meant that an entire Department division would be laid off. Sometimes several. 95 | 96 | After the author had agreed, again, to keep his answers to a minimum, he was asked whether he believes project _Inception_ represents a form of _static reflection_ in Bust, the fast, _safe_, systems programming language, to which he replied: 97 | 98 | > In a limited form, maybe, but the goal of the project wasn't to explore this ... 99 | 100 | The author's unsolicited opinions regarding the fast, safe, Bust systems programming language were, again, dismissed as irrelevant, and the questioning continued. 101 | 102 | The author was asked to state how long this "limited form" of _static reflection_ was possible in Bust, the fast, safe, systems programming language. 103 | 104 | > Since 1.20 maybe, possibly earlier, I ... 105 | 106 | The author was cut off here, and reminded that whatever else he had to say was irrelevant. 107 | 108 | > *The technical advisor expresses his personal frustration here, noting that the author's uncertain response demonstrates a flagrant disregard for rigorous analysis, testing, versioning, and other best-practices, and that he considers the author's disdain for industry-standard code-quality indicators a personal offense.* 109 | 110 | > *An additional note highlights that the technical advisor received 17 Bumpups for this observation from his technical peers, on the basis of encouraging technical excellence.* 111 | 112 | > **Additional Context from the Technical Advisor:** Bumpups, originally invented by the department's elusive code-samurai Douzo Yoroshiku Onegaishimasu, are a highly prized asset across the department, both because of their elaborate distribution scheme involving delicate orchestration of the Department's most advanced probabilistic models across a vast network of satellites (a testament to Douzo's coding prowess), _but even moreso_ because they can be exchanged for legal stimulants at vending machines on department grounds all over the world past 10-PM local time. 113 | 114 | >Each year for the past 15 years had been predicted to be the very last year during which a legal stimulant transaction would take place anywhere in the world unfacilitated by Bumpups, but so far there had always been some upset. Today, the speculation about when exactly this last legal stimulant exchange will occur, down to the nanosecond, is so fiercely competetive, and has so many derivatives and participants, that it is believed to form the backbone of the entire global economy. Uncontacted tribespeople are surveilled around the clock, on the off-chance that they may trade a betel nut or coca leaf, and the amount of energy used by the ever-evolving array of predictive models to determine when exactly this final stimulant exchange will occur is now greater than that of all other human activities combined. It is a truly beautiful system, backed in full by Douzo's sheer genius, and a major reason the department takes technology, specifically Bust, the fast, safe systems programming language, so seriously. _Bust_ is the only fast systems programming language _safe_ enough to be trusted to run the Bumpup infrastructure. Most people think that when this last exchange does occur, money won't exist anymore altogether. Humanity will have moved past that point. But you're not supposed to ask around the department, out of respect for peoples' beliefs and differences. There's even a haiku here: 115 | 116 | > Humanity's fate 117 | 118 | > At the tip of Douzo's blade 119 | 120 | > Patiently waiting 121 | 122 | > No one knows who wrote it. Some even believe it was Douzo himself. The Department Head though, who is widely respected for his fluency in many languages, says it sounds even more beautiful in Douzo's native language, predicted to be the origin of haikus generally: Cantonese. 123 | 124 | The author was then questioned as to whether, in his personal view, he believes project _Inception_ to represent a significant, or even novel development, either to the fast and safe systems programming language, Bust, or to the programming community at large, to which he replied: 125 | 126 | > It seems very unlikely to me, though I wouldn't know for certain ... 127 | 128 | The author was reminded here that the goal was to obtain a firm confirmation or denial of his belief, nothing more. 129 | 130 | The author was asked again, whether he could say with absolute certainty that project _Inception_ represents a significant, novel contribution to the programming community or to Bust, the fast, safe, systems programming language: 131 | 132 | > No 133 | 134 | The author was then asked to share his thoughts on the _safety_ of project _Inception_, about whether it could potentially be misused in a way that would endanger users of Bust, a fast systems programming language which prides itself on being _safe_, or if he believes it to be a danger to the public at large. 135 | 136 | > It was never my intent for it to be misused ... 137 | 138 | Additional statements by the author about the "intended use" of project _Inception_ were dismissed as irrelevant. 139 | 140 | He was asked again to confirm that it would be absolutely impossible to misuse project _Inception_ or its perceived "findings" for any purposes whatsoever, by any actor, regardless of their intent: 141 | 142 | > I suppose.. it would be possible.. 143 | 144 | The author was then asked to provide the specific details on this misuse, in particular with regard to _static reflection_, to which he replied: 145 | 146 | > If the "opt-in" feature is explicitly disabled, that is to say, if the implementor explicitly opts-_in_ to an opt-_out_ mode of functioning, forcing the downstream user to opt-_out_ of any specific implementation instead of opting-_in_, then it might be easier to make a mistake. Easier perhaps to ship a breaking change to a library or set of libraries than the existing alternative, but ... 147 | 148 | The author was asked to clarify whether this would be considered, in his view, a _mistake_, or, whether this was the _intended outcome_ of project _Inception_ from the beginning. Whether project _Inception_ was a deliberate act of sabotage involving the introduction of _static reflection_ to an otherwise unknowning, unprotected, and unaware systems programming language, which was assumed to be _safe_, and whether project _Inception_ was intended to cripple the ecosystem of the Bust systems programming language _by design_, an ecosystem which prides itself on stability and reliability, and which was - at least, prior to project _Inception_, considered to be _safe_. 149 | 150 | > It wasn't intentional, I ... 151 | 152 | The department's system repeated the statement "easier perhaps to ship a breaking change to a library or set of libraries." 153 | 154 | > **The case's Technical Advisor notes here his architectural contributions to the model behind this Questioning feature, and recommends curious users or people looking to enter the field check out his Department-sponsored blog to learn more.** The model is tuned to accept a fixed-length embedding of the case details alongside an input stream of predictions generated from the author's electroencephalogram. The weights themselves are fine-tuned to each individual, and the output is _just_ the voice and intonations predicted to have the best outcome with regard to public safety for the author in question. Importantly, _the actual speech content_ is decoupled completely, so the words can be swapped in and out, but the impact is largely the same! This uses the department's proprietary voice intonation format of course, otherwise it would be nearly impossible - it's _essential_ for difficult cases (though admittedly, this particular author's is straightforward). He notes however that the model was originally designed with the assumption of producing 30-second segments of voice-intonation, so you have to let the author listen for some multiple of 30-seconds, even if less would be sufficient. It's a bit of a "gotcha," he admits, and the one thing he would do differently if he could go back - he cites the "curse of adoption." 155 | 156 | > *The technical advisor received several Bumpups for this explanation in light of his humility.* 157 | 158 | The author was offered a fun-size apple juice box. 159 | 160 | > **Note from the Public Relations Advisor** Department policy is to always give authors the opportunity to raise their own blood-sugar levels, based on biometric indicators. Most don't anyways, but the department always gives them the opportunity, and that's the important part, since it has only been shown to improve public safety outcomes when the choice is provided. Hobbyists sometimes pull apart various models' "hidden layers" in search of some deeper explanation for this, but the professional scientific community has largely abandoned such pursuits as unnecessarily pedantic, due to the clear results. 161 | 162 | The previous question was repeated to the author, shorter and more direct this time: "Was the intent of project _Inception_ to sabotage the Bust systems programming language and its community by introduction of _static reflection_?" The author's response: 163 | 164 | > I.. suppose It could be construed that way but.. 165 | 166 | The author was cut off again and told that whatever else he had to say was irrelevant. 167 | 168 | > **Note from the Psychiatric Advisor**: when dealing with authors having certain criminal dispositions (as is clearly indicated by the predictions from psychiatric models tuned to the history of this one's written and verbal statements) it can be nearly impossible to achieve an outright confession. Pharmacologic intervention has been shown by numerous metrics to significantly improve public safety outcomes _in nearly all cases_, but for _these_ cases the impact is particularly significant. 169 | 170 | > *The psychiatric advisor notes that this author receives her official recommendation for pharmacologic intervention here.* 171 | 172 | It was decided to proceed now with questions of a more personal nature, to establish that the author's character itself was dangerous, given the danger of project _Inception_ had been clearly indicated. 173 | 174 | The author was asked whether he perceives or imagines himself to be a figure of authority in the Bust community, or someone who has been otherwise entrusted with making decisions on the community's behalf, to which he replied: 175 | 176 | > No, I never made ... 177 | 178 | The remainder of the author's statement was dismissed as irrelevant. 179 | 180 | The author was questioned about whether project _Inception_ was released with deliberate intent to endanger the public, to sow feelings of doubt and mistrust among users of the Bust systems programming language. 181 | 182 | > No 183 | 184 | The author was asked whether he considers himself to be the most technically proficient, or "advanced" Bust programmer in the world. Whether he considers himself some kind of "ninja," or perhaps even a "rockstar?" 185 | 186 | > No, certainly not. Please, that's ridiculous.. 187 | 188 | The author was questioned as to whether, from his perspective, the Bust programming language provided insufficient "expressive power" for anything he was trying to achieve, or had some other deficiency, which inspired him to pursue potentially "novel" ways of using the language, outside of its accepted idioms. 189 | 190 | The author did not provide a response within the deadline tailored to the author's profile by generative methods. 191 | 192 | > *The psychiatric advisor notes this as the author's first non-response* 193 | 194 | The author was asked whether he considers himself to be of above-average intelligence, and if this is something he takes pride in. 195 | 196 | > In some areas, maybe ... 197 | 198 | The author's comment is dismissed as irrelevant, and the question is repeated. 199 | 200 | > Yes, I suppose... 201 | 202 | The author is reminded again to provide simple confirmation or denial. 203 | 204 | The author was asked about whether he has delusions of grandeur, hears voices, or perhaps even suffers visions of persecution? 205 | 206 | He did not provide a response within the deadline. 207 | 208 | The author was then asked about whether he imagines himself capable, perhaps on behalf of his "higher-than-average" intelligence, or even the "delusions of grandeur" he may be concealing, of making meaningful, significant, technical contributions to computer science, to Bust, the fast, safe systems programming language, to how that language is used, or to how any other programming language is used, generally. 209 | 210 | The author did not provide a response within the deadline. 211 | 212 | The author was asked whether he envisions himself to be an "explorer," a "pioneer," an "inventor," or otherwise considers it his personal responsibility to "advance" the state-of-the-art in any field. 213 | 214 | The author did not provide a response within the deadline. 215 | 216 | The author was asked whether he thinks of himself as a "prankster," or someone who performs "feats" and "exploits," or who would attempt to make a mockery of Bust, the fast and safe systems programming language, of its users, or even the state of _safe_ systems programming as a whole, whether for personal gain, curiosity, or some distorted sense of "fun" that he had developed. 217 | 218 | The author did not provide a response within the deadline. 219 | 220 | The author was asked if he considers himself capable, mentally, given his current state, of being a responsible practicioner of Bust: the fast, safe systems programming language. 221 | 222 | The author did not provide a response within the deadline. 223 | 224 | The author was asked to spend some time reflecting on the idea that, perhaps.. he is an _imposter_ 225 | 226 | > *The case's Psychiatric Advisor notes here that, this is a feeling not at all uncommon for authors, especially those with a historical or behavioral profile such as this one. On its own, it is actually not even considered much of an issue these days. It is only when symptoms start to show, as in this case, that it becomes of even minor importance to pay much attention to it at all (at least, outside of fringe research, or as an academic curiosity). Having authors reflect on the idea in an environment that is _known to be safe_, has been shown to improve long-term public safety outcomes related to the condition.* 227 | 228 | The author was again offered a fun-size apple juice box, then given some additional time to reflect. 229 | 230 | Despite the author's limited responsiveness, it was assumed by now that visual, audial, biometric, electroencephalographic, and all of the numerous other forms of data collected over the last few questions would (at least once augmented with additional _synthetic_ data extrapolated from the Deparment's full historical record of the author) be sufficient for downstream processing, and that the nature of the questioning could shift again. 231 | 232 | The author was asked if he sees Bust, the fast, safe systems programming language, as some kind of personal-sandbox for himself, or as a toy. 233 | 234 | The author did not provide a response within the deadline. 235 | 236 | The author was given an encouraging reminder that his son's first birthday was coming up. Several members of the questioning team smiled to eachother and the author. It seemed genuine. 237 | 238 | The author was asked why, since he appeared to have so much free-time on his hands to work on _Inception_, did he not simply _"stop"_ and .. spend some time with his son or family instead? Could he not think of anything more helpful or constructive to be doing? Had he developed some kind of compulsion or habitual behavior around Bust, the fast, safe, systems programming language? 239 | 240 | The author did not provide a response within the deadline. 241 | 242 | The psychiatric advisor was considered most qualified to deliver the next question. She began by delivering her sincerest apology about it being suggested that the author present for Questioning so near to such an important day for his son, then suggested that the department would be willing to buy his son a birthday gift. 243 | 244 | She asked whether the author felt that the Department-sponsored opt-in prenatal screening predictions were still accurate, or if there was something else he thought his son would like for his birthday. 245 | 246 | > ... he likes ... dinosaurs 247 | 248 | Members of the questioning team smiled at this. It seemed genuine. 249 | 250 | > **Note from the Technical Advisor** Situations such as this one were difficult for the Department's early conviction models, which were known to enter a peculiar state, wherein their species layer (thought to provide these models some vantage point necessary for making ethical predictions) would classify the questioning team and the author as _different species altogether_. Now, it's important to keep in mind that the model doesn't _actually_ output a particular species, like "Guinea baboon" or "Pink flamingo," but a probability distribution, so you couldn't really say whether the author's distribution or the Questioning Team's looked more "human" than the other. But in this unexpected state, all of the Questioning Team would show distributions that looked, more or less, the same, while the _author_ would show one that was totally different! It resolved on its own after a few minutes, but required manual steps to patch in the downstream data processing and was, for this reason, extremely costly to the department, given the scale of its operations. 251 | 252 | > The Department, who of course had all the best minds working for them already, spent massive amounts of money to resolve this, and when they finally found the solution - a tiny addition, deep in the core of the model architecture - it was elegant, brilliant, and considered a revolution in the field: rather than worrying about fixing the author's distribution, just take the average of the Questioning Teams' and use that average for the author! This addition, called a "shunt," worked beautifully in subsequent pipelines - a smooth integration - and the funniest part is that neither the author's probability distribution nor, of course, those of the Questioning Team, ever needed any modification. The author's distribution would be, as the coders say, "dropped," and then get cleaned up automatically, so long as nothing was ever explicitly done with it at all! 253 | 254 | > *The Technical Advisor received 50+ Bumpups (the maximum that can be shown) for this explanation, citing his depth of knowledge and numerous other qualities. The explanation was even pinned for a short period.* 255 | 256 | The psychiatric advisor began making preparations to move forward with pharmacologic intervention. 257 | 258 | The recommendation for public safety specific to this author from _Shulgunnr-2_, an integrated individualized-medicine model 259 | and pharmacotherapeutic-administration system of which the newer versions are considered to be state-of-the-art, was a regimen consisting of: 260 | 261 | - 50.9ug 1-(4-Bromofuro[2,3-f]benzofuran-8-yl)propan-2-amine 262 | - 2.8ug 1-(3-Chlorophenyl)-4-(2-phenylethyl)piperazine 263 | - 10.2ug dihydroetorphine 264 | 265 | Administered once as an intravenous bolus, followed by continuous infusion of these compounds in 266 | a dynamic ratio, adjusted as necessary based on biometric inputs with the goal of maximizing public 267 | safety outcomes for the duration of infusion. 268 | 269 | > **Note from the Psychiatric Advisor** The Shulgunnr line is one of the Department's earliest technologies, and therefore has an _extremely_ well-established safety record. It has been shown time and again that its recommendations, when used as instructed, are incredibly safe. The only thing to watch out for with these early models like the 2, is that while they have the same convenient quick-selects as the newer models for scaling doses in equestrian and zoological applications, they _don't_ have the colored animal-shaped icons on the display. So it's _very_ important to double-check that the machines are set to "Human" and not "Grizzly bear" or "Black rhinocerous" _before_ hooking up an author. Interns and new-hires are always given a full-color pamphlet containing this information prior to their first independent operation of a Shulgunnr, as a strict matter of Department safety policy. 270 | 271 | Once pharmacologic intervention had been initiated, Questioning Teams were trained to: 272 | 273 | 1. Flatter the author about one of their BitHub achievements. 274 | 2. Proceed quickly to the most pertinent public safety issues, since authors' conditions _could_ degrade rapidly on the off-chance of an adverse reaction. 275 | 276 | The author was asked to confirm that it was indeed him, user 16542714, who authored the code on lines 315-2532 of project _glowstick_, path `src/op/convolution.rs` 277 | 278 | He nodded. 279 | 280 | The author was then notified that, according to Department predictions, the "where-bound" contained on these lines was larger than 99.82% of other successfully compiling Bust where-bounds committed to BitHub, and that for this, the entire Questioning Team extends to him their most sincere congratulations. Several members of the Questioning Team clapped their hands and smiled. It seemed genuine. 281 | 282 | The author smiled. 283 | 284 | > *A note from the Psychiatric Advisor here points out a "nice" marbling of shame through a 15/85 pride-insecurity layer on the author's EEG distributions, with just a speckling of what looks to be some combination of embarassment and perceived irony. She emphasizes that achieving this sort of emotional blend, widely considered **prime** for questioning, is exactly the sort of thing that pharmacologic intervention is designed to help with, and it also indicates a well-selected BitHub sample. She includes her personal recommendation for this portion of the case to be archived as training data.* 285 | 286 | The author was then questioned about whether he had ever conducted experiments regarding _machine-learning_, _tensor-facilitated-statistical-inference_, _parallel-processor-assisted-probabilistic-modeling_, _neural-networks_, or _any_ other _agents_ of an _artificially intelligent_ kind. 287 | 288 | > Yes of course, the project you just mentioned is directly related to those! 289 | 290 | It was clarified to the author that the questioning team already _knew_ about this project and everything on BitHub. The question was intended to determine whether he had done any _other_ work that they _didn't_ know about already. 291 | 292 | > Sure, a few things. In fact, that was what I wanted to try next with project _Inception_. 293 | 294 | A notification then came in that the case had been closed, and the Questioning Team was dismissed. 295 | 296 | A few members smiled as they exited the room. It was 11:42, just in time for lunch. 297 | 298 | > **Case Discussion** The public perception (and, by extension, public safety) of private experiments conducted with _artificial intelligence agents_ was parallel to those of private _chemistry_ experiments in the late 20th century. While there was, technically, _some remote possibility_ that a given private _chemistry_ experiment conducted outside of a commercial or academic institution at that time was legitimate, in the vast majority of cases, it wasn't. Because, for the vast majority of people interested in performing a chemical experiment, there were only two logical goals: drugs or explosives. So the burden of proof shifted to the accused, at least as far as public perception was concerned. The intent with _artificial intelligence agents_ in the current era was even easier to imply. Since the Department _already provided_ models for every predicted necessity, there was only really _one_ logical motive for conducting a private experiment related to _artificial intelligence agents_: to develop a _more powerful_ agent than the Department, and seize the Department by ideological force. Even though that was _exceedingly unlikely_ to ever happen, the Department kept a close eye on the clandestine manufacture of _artificial intelligence agents_. For purposes of public safety. 299 | 300 | > _Static reflection_ was a safety concern for different reasons. On its own, _reflection_ wasn't much of a problem, and it was actually encouraged by the Department for authors to reflect from time-to-time, to keep from bumping into each other and make sure they weren't getting pulled over. As long as everything stayed in motion, the Department's predictions about what would happen next and who would end up where were reasonably accurate. The issue with _static reflection_ was mostly to do with the stasis, because once something _stopped_, it was harder to predict its next movement. An object in stasis became increasingly subject to its own internal state, which was still a bit of a black-box for the Department: a blind-spot on its casino floor. And since the success of the Department's entire public safety program was completely dependent on predictions, _static reflection_ was considered an existential threat to public safety. 301 | 302 | > As for the combination of artifical intelligence agents _with_ static reflection - the Department didn't have any data on this at all, which meant that the fact those two things were even considered safety issues on their own was completely irrelevant to this case, since it would be treated as a _novelty_ case, and novelty cases nearly _always_ led to conviction. This wasn't to say that equipping _artificial intelligence agents_ with _static reflection_ capabilities would actually do anything significant - it most likely wouldn't, given most things didn't. But there was no data about this, and _that_ was an issue. The Department's B++ 26 people would most likely produce some, eventually. 303 | 304 | **Case Results** 305 | - The conviction model outputs showed that the possibility of the author being guilty could not be ruled out, and therefore he was convicted as charged. 306 | - The sentencing model produced (as is usually the case, due at least in part to cost-savings measures implemented by the Department) a single token: `stop`. 307 | 308 | > **Technical Explanation:** This was the stop token, sometimes represented as `<|stop|>` , ``, or `STOP`. Sometimes it even came out in Douzo's native language. Technically, this always meant the same thing: that the model was finished producing outputs and had nothing left to say. Early on, there were various interpretations of this, but those were mostly dismissed as irrelevant once the Department put forward their official stance on the matter: it meant that no one needed to do anything at all. Things could just keep moving along exactly as they were before. It was reasoned that most of these authors appeared to have opted-in to some sort of life-sentence of their own creation anyways, so additional sentencing wouldn't really make much of a difference. 309 | 310 | 311 | The author, now guilty beyond any _reasonable_ doubt, was escorted out of the Questioning facility by the case's Questionaire-Hostess. 312 | 313 | Before he walked off, she handed him a fun-size apple juice box, and a small plastic dinosaur figurine. It was a Compsognathus. 314 | 315 | _"From the department"_ she smiled. It seemed genuine. 316 | 317 | --- 318 | 319 | 320 | This concludes the official account of project _Inception_. 321 | --------------------------------------------------------------------------------