MCPcopy Index your code
hub / github.com/RustPython/RustPython / validate_base_field

Function validate_base_field

crates/derive-impl/src/pyclass.rs:323–374  ·  view source on GitHub ↗

Validates that when a base class is specified, the struct has the base type as its first field. This ensures proper memory layout for subclassing (required for #[repr(transparent)] to work correctly).

(item: &Item, base_path: &syn::Path)

Source from the content-addressed store, hash-verified

321/// Validates that when a base class is specified, the struct has the base type as its first field.
322/// This ensures proper memory layout for subclassing (required for #[repr(transparent)] to work correctly).
323fn validate_base_field(item: &Item, base_path: &syn::Path) -> Result<()> {
324 let Item::Struct(item_struct) = item else {
325 // Only validate structs - enums with base are already an error elsewhere
326 return Ok(());
327 };
328
329 // Get the base type name for error messages
330 let base_name = base_path
331 .segments
332 .last()
333 .map(|s| s.ident.to_string())
334 .unwrap_or_else(|| quote!(#base_path).to_string());
335
336 match &item_struct.fields {
337 syn::Fields::Named(fields) => {
338 let Some(first_field) = fields.named.first() else {
339 bail_span!(
340 item_struct,
341 "#[pyclass] with base = {base_name} requires the first field to be of type {base_name}, but the struct has no fields"
342 );
343 };
344 if !type_matches_path(&first_field.ty, base_path) {
345 bail_span!(
346 first_field,
347 "#[pyclass] with base = {base_name} requires the first field to be of type {base_name}"
348 );
349 }
350 }
351 syn::Fields::Unnamed(fields) => {
352 let Some(first_field) = fields.unnamed.first() else {
353 bail_span!(
354 item_struct,
355 "#[pyclass] with base = {base_name} requires the first field to be of type {base_name}, but the struct has no fields"
356 );
357 };
358 if !type_matches_path(&first_field.ty, base_path) {
359 bail_span!(
360 first_field,
361 "#[pyclass] with base = {base_name} requires the first field to be of type {base_name}"
362 );
363 }
364 }
365 syn::Fields::Unit => {
366 bail_span!(
367 item_struct,
368 "#[pyclass] with base = {base_name} requires the first field to be of type {base_name}, but the struct is a unit struct"
369 );
370 }
371 }
372
373 Ok(())
374}
375
376/// Check if a type matches a given path (handles simple cases like `Foo` or `path::to::Foo`)
377fn type_matches_path(ty: &syn::Type, path: &syn::Path) -> bool {

Callers 1

impl_pyclassFunction · 0.85

Calls 5

type_matches_pathFunction · 0.85
to_stringMethod · 0.80
mapMethod · 0.45
lastMethod · 0.45
firstMethod · 0.45

Tested by

no test coverage detected