PyO3/pyo3 · error · syn::Error
useless `set` - the struct is already annotated with `set_al
Error message
useless `set` - the struct is already annotated with `set_all`
What it means
Compile-time syn error emitted while merging per-field options for #[pyclass]: a field (or the struct) carries an explicit `set` annotation, but the struct is already annotated with `set_all`, which already covers setters for all fields. The redundant `set` is rejected as useless rather than silently ignored, and the span points at the conflicting annotation.
Source
Thrown at pyo3-macros-backend/src/pyclass.rs:340
results
}
}
.into_iter()
.try_combine_syn_errors()?;
if let Some(attr) = args.options.get_all {
for (_, FieldPyO3Options { get, .. }) in &mut field_options {
if let Some(old_get) = get.replace(Annotated::Struct(attr)) {
return Err(syn::Error::new(old_get.span(), DUPE_GET));
}
}
}
if let Some(attr) = args.options.set_all {
for (_, FieldPyO3Options { set, .. }) in &mut field_options {
if let Some(old_set) = set.replace(Annotated::Struct(attr)) {
return Err(syn::Error::new(old_set.span(), DUPE_SET));
}
}
}
impl_class(&class.ident, &args, doc, field_options, methods_type, ctx)
}
enum Annotated<X, Y> {
Field(X),
Struct(Y),
}
impl<X: Spanned, Y: Spanned> Annotated<X, Y> {
fn span(&self) -> Span {
match self {
Self::Field(x) => x.span(),
Self::Struct(y) => y.span(),
}View on GitHub (pinned to ac9b6899d3)
Solutions
- Remove the per-field #[pyo3(set)] attributes where set_all already applies
- Remove set_all if only selected fields should be writable
- Keep explicit per-field set annotations only for fields needing special handling and drop set_all
Example fix
// before
#[pyclass(set_all)]
struct Point {
#[pyo3(set)]
x: f64,
y: f64,
}
// after
#[pyclass(set_all)]
struct Point {
x: f64,
y: f64,
} Defensive patterns
Strategy: validation
Validate before calling
# CI lint: flag #[pyo3(set)] inside structs whose pyclass has set_all # grep -A2 'pyclass(.*set_all' -r src/ | grep 'pyo3(set)' && exit 1
Prevention
- When introducing set_all, remove per-field #[pyo3(set)] in the same commit
- Decide per struct whether mutability is all-or-selected and stick to it
- Run cargo check on PRs to surface the macro error before merging
When it happens
Trigger: Combining #[pyclass(set_all)] with #[pyo3(set)] on one or more fields of the struct.
Common situations: Migrating individual #[pyo3(set)] attributes to set_all without cleanup; template/copy-paste mistakes when adding set_all.
Related errors
- useless `get` - the struct is already annotated with `get_al
- wildcard argument names are not supported
- failed to create type object for `{type_name}`
- Neither abi3 or abi3t features are enabled
- Cannot target an abi3t version below {MINIMUM_SUPPORTED_VERS
AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05).
Data as JSON: /api/errors/979dc80974c4868b.
Report an issue: GitHub.