{"record":{"id":"979dc80974c4868b","repo":"PyO3/pyo3","slug":"useless-set-the-struct-is-already-annotated-wi","errorCode":null,"errorMessage":"useless `set` - the struct is already annotated with `set_all`","messagePattern":"useless `set` - the struct is already annotated with `set_all`","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"pyo3-macros-backend/src/pyclass.rs","lineNumber":340,"sourceCode":"\n            results\n        }\n    }\n    .into_iter()\n    .try_combine_syn_errors()?;\n\n    if let Some(attr) = args.options.get_all {\n        for (_, FieldPyO3Options { get, .. }) in &mut field_options {\n            if let Some(old_get) = get.replace(Annotated::Struct(attr)) {\n                return Err(syn::Error::new(old_get.span(), DUPE_GET));\n            }\n        }\n    }\n\n    if let Some(attr) = args.options.set_all {\n        for (_, FieldPyO3Options { set, .. }) in &mut field_options {\n            if let Some(old_set) = set.replace(Annotated::Struct(attr)) {\n                return Err(syn::Error::new(old_set.span(), DUPE_SET));\n            }\n        }\n    }\n\n    impl_class(&class.ident, &args, doc, field_options, methods_type, ctx)\n}\n\nenum Annotated<X, Y> {\n    Field(X),\n    Struct(Y),\n}\n\nimpl<X: Spanned, Y: Spanned> Annotated<X, Y> {\n    fn span(&self) -> Span {\n        match self {\n            Self::Field(x) => x.span(),\n            Self::Struct(y) => y.span(),\n        }","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/PyO3/pyo3/blob/ac9b6899d348be4d54614d060dea53a645a12e36/pyo3-macros-backend/src/pyclass.rs#L322-L358","documentation":"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.","triggerScenarios":"Combining #[pyclass(set_all)] with #[pyo3(set)] on one or more fields of the struct.","commonSituations":"Migrating individual #[pyo3(set)] attributes to set_all without cleanup; template/copy-paste mistakes when adding set_all.","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"],"exampleFix":"// before\n#[pyclass(set_all)]\nstruct Point {\n    #[pyo3(set)]\n    x: f64,\n    y: f64,\n}\n// after\n#[pyclass(set_all)]\nstruct Point {\n    x: f64,\n    y: f64,\n}","handlingStrategy":"validation","validationCode":"# CI lint: flag #[pyo3(set)] inside structs whose pyclass has set_all\n# grep -A2 'pyclass(.*set_all' -r src/ | grep 'pyo3(set)' && exit 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","pyo3-macros","pyclass","duplicate-attribute"],"backgroundTag":"duplicate-attribute","analyzedSha":"ac9b6899d348be4d54614d060dea53a645a12e36","analyzedAt":"2026-09-05T09:20:35.319Z","contentChangedAt":"2026-09-05T09:20:35.319Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}