rust-lang/rust · error · syn::Error

only one of `skip` or `only` may be specified

Error message

only one of `skip` or `only` may be specified

What it means

Thrown by `for_each_function!`'s `validate` (lib.rs:207) when both `skip` and `only` are specified. These are mutually exclusive filters — `only` already fully determines the set, so `skip` is redundant and ambiguous.

Source

Thrown at library/compiler-builtins/crates/libm-macros/src/lib.rs:207

        .skip
        .iter()
        .chain(only_mentions)
        .chain(attr_mentions)
        .chain(fn_extra_mentions);

    // Make sure that every function mentioned is a real function
    for mentioned in all_mentioned_fns {
        if !ALL_OPERATIONS.iter().any(|func| mentioned == func.name) {
            let e = syn::Error::new(
                mentioned.span(),
                format!("unrecognized function name `{mentioned}`"),
            );
            return Err(e);
        }
    }

    if !input.skip.is_empty() && input.only.is_some() {
        let e = syn::Error::new(
            input.only_span.unwrap(),
            "only one of `skip` or `only` may be specified",
        );
        return Err(e);
    }

    // Construct a list of what we intend to expand
    let mut fn_list = Vec::new();
    for func in ALL_OPERATIONS.iter() {
        let fn_name = func.name;
        // If we have an `only` list and it does _not_ contain this function name, skip it
        if input
            .only
            .as_ref()
            .is_some_and(|only| !only.iter().any(|o| o == fn_name))
        {
            continue;
        }

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Choose one filter: use `only: [...]` to include a specific set, or `skip: [...]` to exclude from the full set.
  2. Remove whichever field is not intended.

Example fix

// before
libm_macros::for_each_function! {
    callback: cb,
    skip: [sin],
    only: [cos, sin],
}

// after
libm_macros::for_each_function! {
    callback: cb,
    only: [cos, sin],
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure at most one of skip/only is set in the macro invocation.
// (Static check: if you template-generate the macro call, branch on which filter is needed.)
let (skip, only) = if let Some(set) = only_set {
    (vec![], Some(set))      // use only
} else {
    (skip_set, None)         // use skip
};

Prevention

When it happens

Trigger: Writing a `for_each_function!` invocation that contains both a `skip: [...]` field and an `only: [...]` field.

Common situations: Incrementally adding an `only` list to narrow scope while forgetting to remove an earlier `skip`, or vice versa.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/234f5166da904571. Report an issue: GitHub.