tracel-ai/burn · error · syn::Error
Generic type `{ident}` should not be used on both a module f
Error message
Generic type `{ident}` should not be used on both a module field and a skipped field. Consider removing `#[module(skip)]` or using a different type for one of the fields. What it means
burn-derive's #[Module] macro rejects a struct whose generics are used both on a module field (a field that generates module code) and on a field marked #[module(skip)]. Skipped fields are excluded from codegen, so if the same generic type parameter appears in both, the generated code would be inconsistent (the generic would be required for the skipped field but not tracked as a module parameter), so the proc macro fails at compile time pointing at the generic parameter.
Source
Thrown at crates/burn-derive/src/module/codegen_struct.rs:349
let field_type = parse_module_field_type(field, generics)?;
if field_type.is_module {
module_generics.extend(field_type.generic_idents.iter().cloned());
} else if matches!(field_type.attr, Some(ModuleFieldAttribute::Skip)) {
skip_generics.extend(field_type.generic_idents.iter().cloned());
}
fields.push(ModuleField::new(field.clone(), field_type));
}
}
syn::Data::Enum(_) => panic!("Only struct can be derived"),
syn::Data::Union(_) => panic!("Only struct can be derived"),
};
for ident in module_generics.intersection(&skip_generics) {
if let Some(param) = ast.generics.params.iter().find_map(|p| match p {
syn::GenericParam::Type(tp) if tp.ident == *ident => Some(tp),
_ => None,
}) {
return Err(syn::Error::new(
param.ident.span(),
format!(
"Generic type `{ident}` should not be used on both a module field and a skipped field. \
Consider removing `#[module(skip)]` or using a different type for one of the fields.",
),
));
}
}
Ok(fields)
}
pub(crate) fn parse_module_field_type(
field: &Field,
generics: &mut ModuleGenerics,
) -> syn::Result<ModuleFieldType> {
let mut field_type = ModuleFieldType::default();
View on GitHub (pinned to d16f7ba2ed)
Solutions
- Remove `#[module(skip)]` from the offending field so it participates in module codegen like the other field using the generic.
- Change the skipped field to a different (concrete or distinct generic) type so the two fields do not share the same generic parameter.
- Make the skipped field generic over a different type parameter (add a new generic) or hardcode its type.
- Store the skipped data outside the Module struct (e.g. in a wrapper struct holding the Module plus the extra field).
Example fix
// before
#[derive(Module)]
struct Net<B: Backend> {
inner: Linear<B>,
#[module(skip)]
aux: Aux<B>, // same generic on skipped field: compile error
}
// after
#[derive(Module)]
struct Net<B: Backend> {
inner: Linear<B>,
#[module(skip)]
aux: Aux<f32>, // or drop #[module(skip)] from aux
} Defensive patterns
Strategy: validation
Validate before calling
// Compile-time: audit #[derive(Module)] structs so no generic ident appears // both on a normal module field and on a #[module(skip)] field. // e.g. `cargo check` fails at the generic param span; fix before building.
Prevention
- Never reuse the same generic parameter on a #[module(skip)] field and a module field.
- Give skipped metadata/config fields concrete types (e.g. usize, String) instead of the backend/model generic.
- When adding #[module(skip)], rename the field's generic or remove the attribute.
- Run `cargo check` early after editing Module derives; this error is reported at compile time with the offending generic named.
When it happens
Trigger: Compiling a #[derive(Module)] struct where one type generic parameter appears on a regular module field (e.g. `inner: Linear<B>`) and also on a `#[module(skip)]` field (e.g. `#[module(skip)] extra: Option<T>`) with the same ident.
Common situations: Reusing a backend generic `B` or model generic `T` on both a real submodule and a skipped metadata/config field; copy-pasting fields and adding #[module(skip)] to one without renaming its generic; migrating structs to skip serialization of some fields.
Related errors
- Autodiff should not wrap an autodiff device.
- unsupported dispatch device: {__other:?}
- an autodiff float primitive must have an enabled autodiff co
- an enabled float tensor must use an autodiff primitive
- ctc_loss: 2 * max_target_len + 1 = {} exceeds the kernel's s
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/8758e1b1c0e525fc.
Report an issue: GitHub.