PyO3/pyo3 · error · syn::Error

wildcard argument names are not supported

Error message

wildcard argument names are not supported

What it means

pyo3's macro backend rejects function/method argument patterns it cannot turn into Python parameter bindings. A wildcard pattern (e.g. `_: Type` or `_name`) carries no identifier, so no Python argument name can be generated, so handle_argument_error errors during macro expansion of parse.

Source

Thrown at pyo3-macros-backend/src/method.rs:214

                    #[cfg(feature = "experimental-inspect")]
                    annotation: None,
                }))
            }
        }
    }
}

fn handle_argument_error(pat: &syn::Pat) -> syn::Error {
    let span = pat.span();
    let msg = match pat {
        syn::Pat::Wild(_) => "wildcard argument names are not supported",
        syn::Pat::Struct(_)
        | syn::Pat::Tuple(_)
        | syn::Pat::TupleStruct(_)
        | syn::Pat::Slice(_) => "destructuring in arguments is not supported",
        _ => "unsupported argument",
    };
    syn::Error::new(span, msg)
}

/// Represents what kind of a function a pyfunction or pymethod is
#[derive(Clone, Debug)]
pub enum FnType {
    /// Represents a pymethod annotated with `#[getter]`
    Getter(SelfType),
    /// Represents a pymethod annotated with `#[setter]`
    Setter(SelfType),
    /// Represents a pymethod annotated with `#[deleter]`
    Deleter(SelfType),
    /// Represents a regular pymethod
    Fn(SelfType),
    /// Represents a pymethod annotated with `#[classmethod]`, like a `@classmethod`
    FnClass(Span),
    /// Represents a pyfunction or a pymethod annotated with `#[staticmethod]`, like a `@staticmethod`
    FnStatic,
    /// Represents a pyfunction annotated with `#[pyo3(pass_module)]

View on GitHub (pinned to ac9b6899d3)

Solutions

  1. Give every argument a real identifier (e.g. `_unused: usize` -> `unused: usize`)
  2. Remove destructuring patterns; accept a named parameter and destructure in the body
  3. For ignored Python args, name the parameter (e.g. `_unused`) — the leading underscore keeps Rust lint-clean

Example fix

// before
#[pyfunction]
fn process(_count: usize) -> usize { _count * 2 }
// after
#[pyfunction]
fn process(count: usize) -> usize { count * 2 }
Defensive patterns

Strategy: validation

Validate before calling

// compile-time macro error; validate signatures by convention before building
// CI check: grep for wildcard params in pyfunctions
// grep -rn 'fn .*(_ *[A-Za-z]' src/  # flag `_: Type` args in #[pyfunction]s

Try / catch

// expand macros early to catch it in review
cargo expand path::to::pyfunction 2>&1 | head -20

Prevention

When it happens

Trigger: Declaring a #[pyfunction]/#[pymethod] parameter with a wildcard pattern such as `_: usize`, or using a destructuring pattern (struct/tuple/slice) in the argument list.

Common situations: Copying Rust idioms like `_unused: i32` into pyfunctions; trying to destructure tuples directly in a pyfunction signature.

Related errors


AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05). Data as JSON: /api/errors/03e117f29b82995a. Report an issue: GitHub.