Skip to content

Commit b95feac

Browse files
wip: Add ShapeFlags, computed_variance, digamma prelude exports, update macro vtable gen
- Add Variance enum with computed_variance() methods to Shape - Add ShapeFlags bitflags with UNTAGGED flag - Add tag/content fields to Shape for enum tagging - Add Field::should_skip_deserializing() helper - Export VTableDirect, VTableErased, Attr, FieldBuilder, ShapeBuilder, Variance, ShapeFlags, HashProxy to digamma prelude - Add 𝟋drop_for helper for vtable construction - Update gen_vtable_instant() to use VTableDirect::builder_for pattern with direct trait refs - Fix facet-pretty ExtensionAttr -> Attr rename
1 parent b2a3c5e commit b95feac

File tree

19 files changed

+495
-136
lines changed

19 files changed

+495
-136
lines changed

facet-core/src/impls/alloc/arc.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -519,15 +519,13 @@ mod tests {
519519
// SAFETY: borrowed_ptr points to a valid String within the Arc
520520
assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
521521

522-
// Get the function pointer for dropping the Arc
523-
let drop_fn = arc_shape
524-
.vtable
525-
.drop_in_place
526-
.expect("Arc<T> should have drop_in_place");
527-
528522
// Drop the Arc in place
529523
// SAFETY: arc_ptr points to a valid Arc<String>
530-
unsafe { drop_fn(OxMut::new(arc_ptr, arc_shape)) };
524+
unsafe {
525+
arc_shape
526+
.call_drop_in_place(arc_ptr)
527+
.expect("Arc<T> should have drop_in_place");
528+
}
531529

532530
// Deallocate the memory
533531
// SAFETY: arc_ptr was allocated by arc_shape and is now dropped (but memory is still valid)
@@ -583,18 +581,15 @@ mod tests {
583581
assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
584582

585583
// 4. Drop everything and free memory
586-
let arc_drop_fn = arc_shape.vtable.drop_in_place.unwrap();
587-
let weak_drop_fn = weak_shape.vtable.drop_in_place.unwrap();
588-
589584
unsafe {
590585
// Drop Arcs
591-
arc_drop_fn(OxMut::new(arc1_ptr, arc_shape));
586+
arc_shape.call_drop_in_place(arc1_ptr).unwrap();
592587
arc_shape.deallocate_mut(arc1_ptr).unwrap();
593-
arc_drop_fn(OxMut::new(arc2_ptr, arc_shape));
588+
arc_shape.call_drop_in_place(arc2_ptr).unwrap();
594589
arc_shape.deallocate_mut(arc2_ptr).unwrap();
595590

596591
// Drop Weak
597-
weak_drop_fn(OxMut::new(weak1_ptr, weak_shape));
592+
weak_shape.call_drop_in_place(weak1_ptr).unwrap();
598593
weak_shape.deallocate_mut(weak1_ptr).unwrap();
599594
}
600595
}
@@ -633,9 +628,8 @@ mod tests {
633628
let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
634629

635630
// 3. Drop and free the strong pointer (arc1)
636-
let arc_drop_fn = arc_shape.vtable.drop_in_place.unwrap();
637631
unsafe {
638-
arc_drop_fn(OxMut::new(arc1_ptr, arc_shape));
632+
arc_shape.call_drop_in_place(arc1_ptr).unwrap();
639633
arc_shape.deallocate_mut(arc1_ptr).unwrap();
640634
}
641635

@@ -652,13 +646,12 @@ mod tests {
652646
);
653647

654648
// 5. Clean up: Deallocate the memory intended for the failed upgrade and drop/deallocate the weak pointer
655-
let weak_drop_fn = weak_shape.vtable.drop_in_place.unwrap();
656649
unsafe {
657650
// Deallocate the *uninitialized* memory allocated for the failed upgrade attempt
658651
arc_shape.deallocate_uninit(arc2_uninit_ptr).unwrap();
659652

660653
// Drop and deallocate the weak pointer
661-
weak_drop_fn(OxMut::new(weak1_ptr, weak_shape));
654+
weak_shape.call_drop_in_place(weak1_ptr).unwrap();
662655
weak_shape.deallocate_mut(weak1_ptr).unwrap();
663656
}
664657
}

facet-core/src/impls/alloc/boxed.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,15 +189,13 @@ mod tests {
189189
// SAFETY: borrowed_ptr points to a valid String within the Box
190190
assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
191191

192-
// Get the function pointer for dropping the Box
193-
let drop_fn = box_shape
194-
.vtable
195-
.drop_in_place()
196-
.expect("Box<T> should have drop_in_place");
197-
198192
// Drop the Box in place
199193
// SAFETY: box_ptr points to a valid Box<String>
200-
unsafe { drop_fn(box_ptr) };
194+
unsafe {
195+
box_shape
196+
.call_drop_in_place(box_ptr)
197+
.expect("Box<T> should have drop_in_place");
198+
}
201199

202200
// Deallocate the memory
203201
// SAFETY: box_ptr was allocated by box_shape and is now dropped (but memory is still valid)

facet-core/src/impls/alloc/btreeset.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ where
111111

112112
#[cfg(test)]
113113
mod tests {
114+
use core::ptr::NonNull;
115+
114116
use alloc::collections::BTreeSet;
115117
use alloc::string::String;
116118
use alloc::vec::Vec;
@@ -159,7 +161,7 @@ mod tests {
159161
let did_insert = unsafe {
160162
(btreeset_def.vtable.insert)(
161163
btreeset_ptr,
162-
PtrMut::new(NonNull::from(&mut new_value)),
164+
PtrMut::new(NonNull::from(&mut new_value).as_ptr()),
163165
)
164166
};
165167

@@ -184,7 +186,7 @@ mod tests {
184186
let did_insert = unsafe {
185187
(btreeset_def.vtable.insert)(
186188
btreeset_ptr,
187-
PtrMut::new(NonNull::from(&mut new_value)),
189+
PtrMut::new(NonNull::from(&mut new_value).as_ptr()),
188190
)
189191
};
190192

@@ -232,14 +234,12 @@ mod tests {
232234
strings_sorted.sort();
233235
assert_eq!(iter_items, strings_sorted);
234236

235-
// Get the function pointer for dropping the BTreeSet
236-
let drop_fn = btreeset_shape
237-
.vtable
238-
.drop_in_place()
239-
.expect("BTreeSet<T> should have drop_in_place");
240-
241237
// Drop the BTreeSet in place
242-
unsafe { drop_fn(btreeset_ptr) };
238+
unsafe {
239+
btreeset_shape
240+
.call_drop_in_place(btreeset_ptr)
241+
.expect("BTreeSet<T> should have drop_in_place");
242+
}
243243

244244
// Deallocate the memory
245245
unsafe { btreeset_shape.deallocate_mut(btreeset_ptr).unwrap() };

facet-core/src/impls/alloc/rc.rs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -774,16 +774,13 @@ mod tests {
774774
// SAFETY: borrowed_ptr points to a valid String within the Rc
775775
assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
776776

777-
// Get the function pointer for dropping the Rc
778-
let drop_fn = rc_shape
779-
.vtable
780-
.drop_in_place()
781-
.expect("Rc<T> should have drop_in_place");
782-
783777
// Drop the Rc in place
784778
// SAFETY: rc_ptr points to a valid Rc<String>
785-
let rc_ox = OxMut::new(rc_ptr, rc_shape);
786-
unsafe { drop_fn(rc_ox) };
779+
unsafe {
780+
rc_shape
781+
.call_drop_in_place(rc_ptr)
782+
.expect("Rc<T> should have drop_in_place");
783+
}
787784

788785
// Deallocate the memory
789786
// SAFETY: rc_ptr was allocated by rc_shape and is now dropped (but memory is still valid)
@@ -821,14 +818,14 @@ mod tests {
821818
let weak1_uninit_ptr = weak_shape.allocate().unwrap();
822819
let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
823820
// SAFETY: rc1_ptr points to a valid Rc, weak1_uninit_ptr is allocated for a Weak
824-
let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr.as_const(), weak1_uninit_ptr) };
821+
let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
825822

826823
// 3. Upgrade weak1 to create a second Rc (rc2)
827824
let rc2_uninit_ptr = rc_shape.allocate().unwrap();
828825
let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
829826
// SAFETY: weak1_ptr points to a valid Weak, rc2_uninit_ptr is allocated for an Rc.
830827
// Upgrade should succeed as rc1 still exists.
831-
let rc2_ptr = unsafe { upgrade_into_fn(weak1_ptr.as_const(), rc2_uninit_ptr) }
828+
let rc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) }
832829
.expect("Upgrade should succeed while original Rc exists");
833830

834831
// Check the content of the upgraded Rc
@@ -839,22 +836,16 @@ mod tests {
839836
assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
840837

841838
// 4. Drop everything and free memory
842-
let rc_drop_fn = rc_shape.vtable.drop_in_place().unwrap();
843-
let weak_drop_fn = weak_shape.vtable.drop_in_place().unwrap();
844-
845839
unsafe {
846840
// Drop Rcs
847-
let rc1_ox = OxMut::new(rc1_ptr, rc_shape);
848-
rc_drop_fn(rc1_ox);
841+
rc_shape.call_drop_in_place(rc1_ptr).unwrap();
849842
rc_shape.deallocate_mut(rc1_ptr).unwrap();
850843

851-
let rc2_ox = OxMut::new(rc2_ptr, rc_shape);
852-
rc_drop_fn(rc2_ox);
844+
rc_shape.call_drop_in_place(rc2_ptr).unwrap();
853845
rc_shape.deallocate_mut(rc2_ptr).unwrap();
854846

855847
// Drop Weak
856-
let weak1_ox = OxMut::new(weak1_ptr, weak_shape);
857-
weak_drop_fn(weak1_ox);
848+
weak_shape.call_drop_in_place(weak1_ptr).unwrap();
858849
weak_shape.deallocate_mut(weak1_ptr).unwrap();
859850
}
860851
}
@@ -890,21 +881,19 @@ mod tests {
890881
let weak1_uninit_ptr = weak_shape.allocate().unwrap();
891882
let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
892883
// SAFETY: rc1_ptr is valid, weak1_uninit_ptr is allocated for Weak
893-
let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr.as_const(), weak1_uninit_ptr) };
884+
let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
894885

895886
// 3. Drop and free the strong pointer (rc1)
896-
let rc_drop_fn = rc_shape.vtable.drop_in_place().unwrap();
897887
unsafe {
898-
let rc1_ox = OxMut::new(rc1_ptr, rc_shape);
899-
rc_drop_fn(rc1_ox);
888+
rc_shape.call_drop_in_place(rc1_ptr).unwrap();
900889
rc_shape.deallocate_mut(rc1_ptr).unwrap();
901890
}
902891

903892
// 4. Attempt to upgrade the weak pointer (weak1)
904893
let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
905894
let rc2_uninit_ptr = rc_shape.allocate().unwrap();
906895
// SAFETY: weak1_ptr is valid (though points to dropped data), rc2_uninit_ptr is allocated for Rc
907-
let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr.as_const(), rc2_uninit_ptr) };
896+
let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) };
908897

909898
// Assert that the upgrade failed
910899
assert!(
@@ -913,14 +902,12 @@ mod tests {
913902
);
914903

915904
// 5. Clean up: Deallocate the memory intended for the failed upgrade and drop/deallocate the weak pointer
916-
let weak_drop_fn = weak_shape.vtable.drop_in_place().unwrap();
917905
unsafe {
918906
// Deallocate the *uninitialized* memory allocated for the failed upgrade attempt
919907
rc_shape.deallocate_uninit(rc2_uninit_ptr).unwrap();
920908

921909
// Drop and deallocate the weak pointer
922-
let weak1_ox = OxMut::new(weak1_ptr, weak_shape);
923-
weak_drop_fn(weak1_ox);
910+
weak_shape.call_drop_in_place(weak1_ptr).unwrap();
924911
weak_shape.deallocate_mut(weak1_ptr).unwrap();
925912
}
926913
}

facet-core/src/impls/alloc/string.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ mod tests {
3030
use core::ptr::NonNull;
3131

3232
use crate::Facet;
33-
use crate::ptr::PtrUninit;
3433
use alloc::string::String;
3534

3635
#[test]
@@ -47,28 +46,27 @@ mod tests {
4746
fn test_string_parse() {
4847
// Test that we can parse a string into a String
4948
let shape = String::SHAPE;
50-
let parse_fn = shape.vtable.parse().unwrap();
5149

5250
// Allocate memory for the String
5351
let layout = shape.layout.sized_layout().unwrap();
5452
let ptr = unsafe { alloc::alloc::alloc(layout) };
5553
let Some(ptr) = NonNull::new(ptr) else {
5654
alloc::alloc::handle_alloc_error(layout)
5755
};
58-
let uninit = PtrUninit::new(ptr);
56+
let ptr_mut = crate::PtrMut::new(ptr.as_ptr());
5957

60-
// Parse the string
61-
let result = unsafe { parse_fn("hello world", uninit) };
62-
assert!(result.is_ok());
58+
// Parse the string using the new API
59+
let result = unsafe { shape.call_parse("hello world", ptr_mut) };
60+
assert!(result.is_some(), "String should have parse function");
61+
assert!(result.unwrap().is_ok());
6362

6463
// Get the parsed value
65-
let ptr_mut = result.unwrap();
6664
let parsed = unsafe { ptr_mut.get::<String>() };
6765
assert_eq!(parsed, &String::from("hello world"));
6866

6967
// Clean up
7068
unsafe {
71-
ptr_mut.drop_in_place::<String>();
69+
shape.call_drop_in_place(ptr_mut).unwrap();
7270
alloc::alloc::dealloc(ptr.as_ptr(), layout);
7371
}
7472
}

facet-core/src/impls/core/pointer.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *mut T {
168168
#[cfg(test)]
169169
mod test {
170170
use core::panic::{RefUnwindSafe, UnwindSafe};
171+
172+
#[cfg(feature = "auto-traits")]
171173
use impls::impls;
172174

173175
#[allow(unused)]
@@ -190,6 +192,7 @@ mod test {
190192
}
191193

192194
#[test]
195+
#[cfg(feature = "auto-traits")]
193196
fn mut_ref_not_unwind_safe() {
194197
assert!(impls!(&mut (): !UnwindSafe));
195198
}

facet-core/src/impls/std/hashset.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,10 @@ mod tests {
293293

294294
// Insert the value
295295
let did_insert = unsafe {
296-
(hashset_def.vtable.insert)(hashset_ptr, PtrMut::new(NonNull::from(&mut new_value)))
296+
(hashset_def.vtable.insert)(
297+
hashset_ptr,
298+
PtrMut::new(NonNull::from(&mut new_value).as_ptr()),
299+
)
297300
};
298301

299302
assert!(did_insert, "expected value to be inserted in the HashSet");
@@ -311,7 +314,10 @@ mod tests {
311314

312315
// Try to insert the value
313316
let did_insert = unsafe {
314-
(hashset_def.vtable.insert)(hashset_ptr, PtrMut::new(NonNull::from(&mut new_value)))
317+
(hashset_def.vtable.insert)(
318+
hashset_ptr,
319+
PtrMut::new(NonNull::from(&mut new_value).as_ptr()),
320+
)
315321
};
316322

317323
assert!(
@@ -353,16 +359,14 @@ mod tests {
353359
// Ensure the iterator returned all of the strings
354360
assert_eq!(iter_items, strings.iter().copied().collect::<HashSet<_>>());
355361

356-
// Get the function pointer for dropping the HashSet
357-
let drop_fn = hashset_shape
358-
.vtable
359-
.drop_in_place()
360-
.expect("HashSet<T> should have drop_in_place");
361-
362362
// Drop the HashSet in place
363-
unsafe { drop_fn(hashset_ptr) };
363+
unsafe {
364+
hashset_shape
365+
.call_drop_in_place(hashset_ptr)
366+
.expect("HashSet<T> should have drop_in_place");
364367

365-
// Deallocate the memory
366-
unsafe { hashset_shape.deallocate_mut(hashset_ptr).unwrap() };
368+
// Deallocate the memory
369+
hashset_shape.deallocate_mut(hashset_ptr).unwrap();
370+
}
367371
}
368372
}

facet-core/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,29 @@ pub unsafe trait Facet<'facet>: 'facet {
5555
#[allow(nonstandard_style)]
5656
pub mod 𝟋 {
5757
// === Type aliases ===
58+
pub use crate::Attr as 𝟋Attr;
5859
pub use crate::Def as 𝟋Def;
5960
pub use crate::EnumRepr as 𝟋ERpr;
6061
pub use crate::EnumType as 𝟋ETy;
6162
pub use crate::Facet as 𝟋Fct;
6263
pub use crate::Field as 𝟋Fld;
64+
pub use crate::FieldBuilder as 𝟋FldB;
6365
pub use crate::FieldFlags as 𝟋FF;
66+
pub use crate::HashProxy as 𝟋HP;
6467
pub use crate::MarkerTraits as 𝟋Mt;
6568
pub use crate::Repr as 𝟋Repr;
6669
pub use crate::Shape as 𝟋Shp;
70+
pub use crate::ShapeBuilder as 𝟋ShpB;
71+
pub use crate::ShapeFlags as 𝟋ShpF;
6772
pub use crate::ShapeRef as 𝟋ShpR;
6873
pub use crate::StructKind as 𝟋Sk;
6974
pub use crate::StructType as 𝟋STy;
7075
pub use crate::Type as 𝟋Ty;
7176
pub use crate::UserType as 𝟋UTy;
7277
pub use crate::VTable as 𝟋Vt;
78+
pub use crate::VTableDirect as 𝟋VtD;
79+
pub use crate::VTableErased as 𝟋VtE;
80+
pub use crate::Variance as 𝟋Vnc;
7381
pub use crate::Variant as 𝟋Var;
7482

7583
// === ShapeRef variants (for compact codegen) ===
@@ -102,4 +110,10 @@ pub mod 𝟋 {
102110
/// but we need a type for compilation in no_std contexts.
103111
#[cfg(not(feature = "alloc"))]
104112
pub type 𝟋Str = &'static str;
113+
114+
// === Helper functions ===
115+
/// Returns `drop_in_place::<T>` as a function pointer for vtable construction.
116+
pub const fn 𝟋drop_for<T>() -> unsafe fn(*mut T) {
117+
::core::ptr::drop_in_place::<T>
118+
}
105119
}

facet-core/src/types/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,7 @@ pub use error::*;
5858
// Characteristic enum
5959
mod characteristic;
6060
pub use characteristic::*;
61+
62+
// Variance types
63+
mod variance;
64+
pub use variance::*;

0 commit comments

Comments
 (0)