swc-project/swc · error

Unknown visitor type

Error message

Unknown visitor type: {:?}

What it means

The #[parallel] proc macro (swc_ecma_transforms_macros) works only on impl blocks for the Fold or VisitMut traits; it inspects the trait path segment to pick a Mode. When the impl is for any other trait, expansion aborts with `unimplemented!("Unknown visitor type")`. Note that an inherent impl (no trait at all) panics even earlier on `item.trait_.as_ref().unwrap()`.

Solutions

  1. Implement and annotate the Fold or VisitMut trait instead: `#[parallel] impl VisitMut for MyVisitor { ... }`
  2. If you need parallel traversal for another trait, hand-write the rayon-based loop instead of using the macro
  3. Remove the #[parallel] attribute if parallelism is not required

Example fix

// before
#[parallel]
impl Visit for MyVisitor {
    // ...
}

// after
#[parallel]
impl VisitMut for MyVisitor {
    // ...
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the impl target before annotating (compile-time review):
// the trait path's last segment must be exactly `Fold` or `VisitMut`.
const SUPPORTED = new Set(['Fold', 'VisitMut']);
const traitName = implNode.traitPath.lastSegment.identifier; // pseudo
if (!SUPPORTED.has(traitName)) throw new Error('#[parallel] supports Fold/VisitMut only');

Prevention

When it happens

Trigger: Annotating an impl block with #[parallel] where the trait is neither Fold nor VisitMut, e.g. `#[parallel] impl Visit for MyVisitor { ... }` or `#[parallel] impl MyTrait for X { ... }`.

Common situations: Porting a visitor from the deprecated Visit trait (or a custom trait) to the parallel helpers, or applying #[parallel] by copy-paste onto an unrelated impl block.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/12320d91354c58da. Report an issue: GitHub.

Appendix: source

Thrown at crates/swc_ecma_transforms_macros/src/parallel.rs:16

#![allow(non_snake_case)]

use proc_macro2::{Span, TokenStream};
use syn::{parse_quote, Expr, Ident, ImplItem, ImplItemFn, ItemImpl, Meta, Type};

use crate::common::Mode;

pub fn expand(attr: TokenStream, mut item: ItemImpl) -> ItemImpl {
    let mode = {
        let p = &item.trait_.as_ref().unwrap().1;
        if p.is_ident("Fold") {
            Mode::Fold
        } else if p.is_ident("VisitMut") {
            Mode::VisitMut
        } else {
            unimplemented!("Unknown visitor type: {:?}", p)
        }
    };
    let meta = if attr.is_empty() {
        None
    } else {
        Some(syn::parse2::<Meta>(attr).expect("failed to parse meta"))
    };
    let explode = meta
        .as_ref()
        .map(|v| v.path().is_ident("explode"))
        .unwrap_or(false);

    item.items.push(ImplItem::Fn(make_par_visit_method(
        mode,
        "module_items",
        explode,
    )));
    item.items

View on GitHub (pinned to 5176682b65)