1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use super::*;
////////////////////////////////////////////////////////////////////////////////////////////////////
// Build
////////////////////////////////////////////////////////////////////////////////////////////////////
impl<'facet, const BORROW: bool> Partial<'facet, BORROW> {
/// Builds the value, consuming the Partial.
pub fn build(mut self) -> Result<HeapValue<'facet, BORROW>, ReflectError> {
if self.frames().len() != 1 {
return Err(ReflectError::InvariantViolation {
invariant: "Partial::build() expects a single frame — call end() until that's the case",
});
}
let frame = self.frames_mut().last_mut().unwrap();
// Fill in defaults for any unset fields before checking initialization
crate::trace!(
"build(): calling fill_defaults for {}, tracker={:?}, is_init={}",
frame.allocated.shape(),
frame.tracker.kind(),
frame.is_init
);
frame.fill_defaults()?;
crate::trace!(
"build(): after fill_defaults, tracker={:?}, is_init={}",
frame.tracker.kind(),
frame.is_init
);
let frame = self.frames_mut().pop().unwrap();
// Check initialization before proceeding
crate::trace!(
"build(): calling require_full_initialization, tracker={:?}",
frame.tracker.kind()
);
let init_result = frame.require_full_initialization();
crate::trace!(
"build(): require_full_initialization returned {:?}",
init_result.is_ok()
);
if let Err(e) = init_result {
// Put the frame back so Drop can handle cleanup properly
self.frames_mut().push(frame);
return Err(e);
}
// Check invariants if present
// Safety: The value is fully initialized at this point (we just checked with require_full_initialization)
let value_ptr = unsafe { frame.data.assume_init().as_const() };
if let Some(result) = unsafe { frame.allocated.shape().call_invariants(value_ptr) } {
match result {
Ok(()) => {
// Invariants passed
}
Err(message) => {
// Put the frame back so Drop can handle cleanup properly
let shape = frame.allocated.shape();
self.frames_mut().push(frame);
return Err(ReflectError::UserInvariantFailed { message, shape });
}
}
}
// Mark as built to prevent Drop from cleaning up the value
self.state = PartialState::Built;
match frame
.allocated
.shape()
.layout
.sized_layout()
.map_err(|_layout_err| ReflectError::Unsized {
shape: frame.allocated.shape(),
operation: "build (final check for sized layout)",
}) {
Ok(layout) => {
// Determine if we should deallocate based on ownership
let should_dealloc = frame.ownership.needs_dealloc();
Ok(HeapValue {
guard: Some(Guard {
ptr: unsafe { NonNull::new_unchecked(frame.data.as_mut_byte_ptr()) },
layout,
should_dealloc,
}),
shape: frame.allocated.shape(),
phantom: PhantomData,
})
}
Err(e) => {
// Put the frame back for proper cleanup
self.frames_mut().push(frame);
Err(e)
}
}
}
}