• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

facet-rs / facet / 19745466658

27 Nov 2025 06:45PM UTC coverage: 56.188% (+0.7%) from 55.525%
19745466658

Pull #935

github

web-flow
Merge b4bd5e3fa into 9dec07b1e
Pull Request #935: Fix CI issues: miri guard, dead code, and feature gate

10 of 14 new or added lines in 4 files covered. (71.43%)

71 existing lines in 2 files now uncovered.

6293 of 11200 relevant lines covered (56.19%)

122.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

52.23
/facet-reflect/src/partial/partial_api/fields.rs
1
use super::*;
2

3
////////////////////////////////////////////////////////////////////////////////////////////////////
4
// Field selection
5
////////////////////////////////////////////////////////////////////////////////////////////////////
6
impl Partial<'_> {
7
    /// Find the index of a field by name in the current struct
8
    ///
9
    /// If the current frame isn't a struct or an enum (with a selected variant)
10
    /// then this returns `None` for sure.
11
    pub fn field_index(&self, field_name: &str) -> Option<usize> {
×
12
        let frame = self.frames().last()?;
×
13

14
        match frame.shape.ty {
×
15
            Type::User(UserType::Struct(struct_def)) => {
×
16
                struct_def.fields.iter().position(|f| f.name == field_name)
×
17
            }
18
            Type::User(UserType::Enum(_)) => {
19
                // If we're in an enum variant, check its fields
20
                if let Tracker::Enum { variant, .. } = &frame.tracker {
×
21
                    variant
×
22
                        .data
×
23
                        .fields
×
24
                        .iter()
×
25
                        .position(|f| f.name == field_name)
×
26
                } else {
27
                    None
×
28
                }
29
            }
30
            _ => None,
×
31
        }
32
    }
×
33

34
    /// Check if a struct field at the given index has been set
35
    pub fn is_field_set(&self, index: usize) -> Result<bool, ReflectError> {
22✔
36
        let frame = self.frames().last().ok_or(ReflectError::NoActiveFrame)?;
22✔
37

38
        match &frame.tracker {
22✔
39
            Tracker::Uninit => Ok(false),
13✔
40
            Tracker::Init => Ok(true),
2✔
41
            Tracker::Struct { iset, .. } => Ok(iset.get(index)),
7✔
42
            Tracker::Enum { data, variant, .. } => {
×
43
                // Check if the field is already marked as set
44
                if data.get(index) {
×
45
                    return Ok(true);
×
46
                }
×
47

48
                // For enum variant fields that are empty structs, they are always initialized
49
                if let Some(field) = variant.data.fields.get(index) {
×
50
                    if let Type::User(UserType::Struct(field_struct)) = field.shape().ty {
×
51
                        if field_struct.fields.is_empty() {
×
52
                            return Ok(true);
×
53
                        }
×
54
                    }
×
55
                }
×
56

57
                Ok(false)
×
58
            }
59
            Tracker::Option { building_inner } => {
×
60
                // For Options, index 0 represents the inner value
61
                if index == 0 {
×
62
                    Ok(!building_inner)
×
63
                } else {
64
                    Err(ReflectError::InvalidOperation {
×
65
                        operation: "is_field_set",
×
66
                        reason: "Option only has one field (index 0)",
×
67
                    })
×
68
                }
69
            }
70
            _ => Err(ReflectError::InvalidOperation {
×
71
                operation: "is_field_set",
×
72
                reason: "Current frame is not a struct, enum variant, or option",
×
73
            }),
×
74
        }
75
    }
22✔
76

77
    /// Selects a field (by name) of a struct or enum data.
78
    ///
79
    /// For enums, the variant needs to be selected first, see [Self::select_nth_variant]
80
    /// and friends.
81
    pub fn begin_field(&mut self, field_name: &str) -> Result<&mut Self, ReflectError> {
1,080✔
82
        self.require_active()?;
1,080✔
83

84
        let frame = self.frames().last().unwrap();
1,080✔
85
        let fields = self.get_fields()?;
1,080✔
86
        let Some(idx) = fields.iter().position(|f| f.name == field_name) else {
2,222✔
87
            return Err(ReflectError::FieldError {
161✔
88
                shape: frame.shape,
161✔
89
                field_error: facet_core::FieldError::NoSuchField,
161✔
90
            });
161✔
91
        };
92
        self.begin_nth_field(idx)
807✔
93
    }
1,080✔
94

95
    /// Begins the nth field of a struct, enum variant, or array, by index.
96
    ///
97
    /// On success, this pushes a new frame which must be ended with a call to [Partial::end]
98
    pub fn begin_nth_field(&mut self, idx: usize) -> Result<&mut Self, ReflectError> {
992✔
99
        self.require_active()?;
992✔
100

101
        // In deferred mode, get the field name for path tracking and check for stored frames.
102
        // Only track the path if we're at a "navigable" level - i.e., the path length matches
103
        // the expected depth (frames.len() - 1). If we're inside a collection item, the path
104
        // will be shorter than expected, so we shouldn't add to it.
105
        let field_name = self.get_field_name_for_path(idx);
992✔
106

107
        // Update current_path in deferred mode
108
        if let FrameMode::Deferred {
109
            stack,
242✔
110
            start_depth,
242✔
111
            current_path,
242✔
112
            stored_frames,
242✔
113
            ..
114
        } = &mut self.mode
992✔
115
        {
116
            // Only track path if we're at the expected navigable depth
117
            // Path should have (frames.len() - start_depth) entries before we add this field
118
            let relative_depth = stack.len() - *start_depth;
242✔
119
            let should_track = current_path.len() == relative_depth;
242✔
120

121
            if let Some(name) = field_name {
242✔
122
                if should_track {
235✔
123
                    current_path.push(name);
227✔
124

125
                    // Check if we have a stored frame for this path
126
                    if let Some(stored_frame) = stored_frames.remove(current_path) {
227✔
127
                        trace!(
128
                            "begin_nth_field: Restoring stored frame for path {:?}",
129
                            current_path
130
                        );
131

132
                        // Update parent's current_child tracking
133
                        let frame = stack.last_mut().unwrap();
48✔
134
                        frame.tracker.set_current_child(idx);
48✔
135

136
                        stack.push(stored_frame);
48✔
137
                        return Ok(self);
48✔
138
                    }
179✔
139
                }
8✔
140
            }
7✔
141
        }
750✔
142

143
        let frame = self.frames_mut().last_mut().unwrap();
944✔
144

145
        let next_frame = match frame.shape.ty {
944✔
146
            Type::User(user_type) => match user_type {
899✔
147
                UserType::Struct(struct_type) => {
832✔
148
                    Self::begin_nth_struct_field(frame, struct_type, idx)?
832✔
149
                }
150
                UserType::Enum(_) => {
151
                    // Check if we have a variant selected
152
                    match &frame.tracker {
64✔
153
                        Tracker::Enum { variant, .. } => {
63✔
154
                            Self::begin_nth_enum_field(frame, variant, idx)?
63✔
155
                        }
156
                        _ => {
157
                            return Err(ReflectError::OperationFailed {
1✔
158
                                shape: frame.shape,
1✔
159
                                operation: "must call select_variant before selecting enum fields",
1✔
160
                            });
1✔
161
                        }
162
                    }
163
                }
164
                UserType::Union(_) => {
165
                    return Err(ReflectError::OperationFailed {
×
UNCOV
166
                        shape: frame.shape,
×
UNCOV
167
                        operation: "cannot select a field from a union",
×
UNCOV
168
                    });
×
169
                }
170
                UserType::Opaque => {
171
                    return Err(ReflectError::OperationFailed {
3✔
172
                        shape: frame.shape,
3✔
173
                        operation: "cannot select a field from an opaque type",
3✔
174
                    });
3✔
175
                }
176
            },
177
            Type::Sequence(sequence_type) => match sequence_type {
44✔
178
                SequenceType::Array(array_type) => {
44✔
179
                    Self::begin_nth_array_element(frame, array_type, idx)?
44✔
180
                }
181
                SequenceType::Slice(_) => {
182
                    return Err(ReflectError::OperationFailed {
×
UNCOV
183
                        shape: frame.shape,
×
UNCOV
184
                        operation: "cannot select a field from slices yet",
×
UNCOV
185
                    });
×
186
                }
187
            },
188
            _ => {
189
                return Err(ReflectError::OperationFailed {
1✔
190
                    shape: frame.shape,
1✔
191
                    operation: "cannot select a field from this type",
1✔
192
                });
1✔
193
            }
194
        };
195

196
        self.frames_mut().push(next_frame);
916✔
197
        Ok(self)
916✔
198
    }
992✔
199

200
    /// Get the field name for path tracking (used in deferred mode)
201
    fn get_field_name_for_path(&self, idx: usize) -> Option<&'static str> {
992✔
202
        let frame = self.frames().last()?;
992✔
203
        match frame.shape.ty {
947✔
204
            Type::User(UserType::Struct(struct_type)) => {
880✔
205
                struct_type.fields.get(idx).map(|f| f.name)
880✔
206
            }
207
            Type::User(UserType::Enum(_)) => {
208
                if let Tracker::Enum { variant, .. } = &frame.tracker {
64✔
209
                    variant.data.fields.get(idx).map(|f| f.name)
63✔
210
                } else {
211
                    None
1✔
212
                }
213
            }
214
            // For arrays, we could use index as string, but for now return None
215
            _ => None,
48✔
216
        }
217
    }
992✔
218

219
    /// Sets the given field to its default value, preferring:
220
    ///
221
    ///   * A `default = some_fn()` function
222
    ///   * The field's `Default` implementation if any
223
    ///
224
    /// But without going all the way up to the parent struct's `Default` impl.
225
    ///
226
    /// Errors out if idx is out of bound, if the field has no default method or Default impl.
227
    pub fn set_nth_field_to_default(&mut self, idx: usize) -> Result<&mut Self, ReflectError> {
×
228
        self.require_active()?;
×
229

230
        let frame = self.frames().last().unwrap();
×
231
        let fields = self.get_fields()?;
×
232

233
        if idx >= fields.len() {
×
234
            return Err(ReflectError::OperationFailed {
×
235
                shape: frame.shape,
×
UNCOV
236
                operation: "field index out of bounds",
×
237
            });
×
UNCOV
238
        }
×
239

240
        let field = fields[idx];
×
241

242
        // Check for field-level default function first, then type-level default
UNCOV
243
        if let Some(field_default_fn) = field.vtable.default_fn {
×
244
            self.begin_nth_field(idx)?;
×
245
            // the field default fn should be well-behaved
246
            unsafe {
247
                self.set_from_function(|ptr| {
×
UNCOV
248
                    field_default_fn(ptr);
×
249
                    Ok(())
×
250
                })?;
×
251
            }
252
            self.end()
×
253
        } else if field.shape().is(Characteristic::Default) {
×
UNCOV
254
            self.begin_nth_field(idx)?;
×
255
            self.set_default()?;
×
256
            self.end()
×
257
        } else {
UNCOV
258
            return Err(ReflectError::DefaultAttrButNoDefaultImpl {
×
259
                shape: field.shape(),
×
UNCOV
260
            });
×
261
        }
UNCOV
262
    }
×
263

264
    /// Given a `Partial` for the same shape, and assuming that partial has the nth
265
    /// field initialized, move the value from `src` to `self`, marking it as deinitialized
266
    /// in `src`.
267
    pub fn steal_nth_field(
2✔
268
        &mut self,
2✔
269
        src: &mut Partial,
2✔
270
        field_index: usize,
2✔
271
    ) -> Result<&mut Self, ReflectError> {
2✔
272
        let dst_shape = self.shape();
2✔
273
        let src_shape = src.shape();
2✔
274
        if dst_shape != src_shape {
2✔
275
            return Err(ReflectError::HeistCancelledDifferentShapes {
×
UNCOV
276
                src_shape,
×
UNCOV
277
                dst_shape,
×
UNCOV
278
            });
×
279
        }
2✔
280

281
        // FIXME: what about enums? we don't check that the right variant is
282
        // selected here.
283
        if !src.is_field_set(field_index)? {
2✔
UNCOV
284
            return Err(ReflectError::InvariantViolation {
×
UNCOV
285
                invariant: "stolen field must be initialized",
×
UNCOV
286
            });
×
287
        }
2✔
288

289
        let maybe_fields = match src_shape.ty {
2✔
UNCOV
290
            Type::Primitive(_primitive_type) => None,
×
291
            Type::Sequence(_sequence_type) => None,
×
292
            Type::User(user_type) => match user_type {
2✔
293
                UserType::Struct(struct_type) => Some(struct_type.fields),
2✔
294
                UserType::Enum(_enum_type) => match self.selected_variant() {
×
295
                    Some(variant) => Some(variant.data.fields),
×
296
                    None => {
UNCOV
297
                        return Err(ReflectError::InvariantViolation {
×
UNCOV
298
                            invariant: "enum field thief must have variant selected",
×
299
                        });
×
300
                    }
301
                },
302
                UserType::Union(_union_type) => None,
×
UNCOV
303
                UserType::Opaque => None,
×
304
            },
UNCOV
305
            Type::Pointer(_pointer_type) => None,
×
306
        };
307

308
        let Some(fields) = maybe_fields else {
2✔
309
            return Err(ReflectError::OperationFailed {
×
UNCOV
310
                shape: src_shape,
×
UNCOV
311
                operation: "fetching field list for steal_nth_field",
×
UNCOV
312
            });
×
313
        };
314

315
        if field_index >= fields.len() {
2✔
316
            return Err(ReflectError::OperationFailed {
×
UNCOV
317
                shape: src_shape,
×
UNCOV
318
                operation: "field index out of bounds",
×
UNCOV
319
            });
×
320
        }
2✔
321
        let field = fields[field_index];
2✔
322

323
        let src_frame = src.frames_mut().last_mut().unwrap();
2✔
324

325
        self.begin_nth_field(field_index)?;
2✔
326
        unsafe {
327
            self.set_from_function(|dst_field_ptr| {
2✔
328
                let src_field_ptr = src_frame.data.field_init_at(field.offset).as_const();
2✔
329
                dst_field_ptr
2✔
330
                    .copy_from(src_field_ptr, field.shape())
2✔
331
                    .unwrap();
2✔
332
                Ok(())
2✔
333
            })?;
2✔
334
        }
335
        self.end()?;
2✔
336

337
        // now mark field as uninitialized in `src`
338
        match &mut src_frame.tracker {
2✔
339
            Tracker::Uninit => {
UNCOV
340
                unreachable!("we just stole a field from src, it couldn't have been fully uninit")
×
341
            }
342
            Tracker::Init => {
343
                // all struct fields were init so we don't even have a struct tracker,
344
                // let's make one!
345
                let mut iset = ISet::new(fields.len());
1✔
346
                iset.set_all();
1✔
347
                iset.unset(field_index);
1✔
348
                src_frame.tracker = Tracker::Struct {
1✔
349
                    iset,
1✔
350
                    current_child: None,
1✔
351
                }
1✔
352
            }
UNCOV
353
            Tracker::Array { .. } => unreachable!("can't steal fields from arrays"),
×
354
            Tracker::Struct { iset, .. } => {
1✔
355
                iset.unset(field_index);
1✔
356
            }
1✔
357
            Tracker::SmartPointer { .. } => {
358
                unreachable!("can't steal fields from smart pointers")
×
359
            }
360
            Tracker::SmartPointerSlice { .. } => {
361
                unreachable!("can't steal fields from smart pointer slices")
×
362
            }
UNCOV
363
            Tracker::Enum { data, .. } => {
×
364
                data.unset(field_index);
×
UNCOV
365
            }
×
366
            Tracker::List { .. } => {
367
                unreachable!("can't steal fields from lists")
×
368
            }
369
            Tracker::Map { .. } => {
370
                unreachable!("can't steal fields from maps")
×
371
            }
372
            Tracker::Set { .. } => {
373
                unreachable!("can't steal fields from sets")
×
374
            }
375
            Tracker::Option { .. } => {
UNCOV
376
                unreachable!("can't steal fields from options")
×
377
            }
378
        }
379

380
        Ok(self)
2✔
381
    }
2✔
382
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc