Repository: swc-project/swc (rust)

Issue:
Deserialization is too slow
Problematic file is https://github.com/swc-project/swc/blob/b52240d8e56f557801d8ffa3d44ad03610e8b5b5/crates/ast_node/src/enum_deserialize.rs#L25-L183

and the problem is that it is calling `ContentRefDeserializer::<D::Error>::new` too many times.


# Solution

I used `cargo expand` on the following file.

```rust

use serde::{Deserialize, Serialize};

#[derive(Deserialize)]
#[serde(tag = "type")]
enum Message {
    Request(String),
    Response(u8),
}

```

and output is

```rust

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use serde::{Deserialize, Serialize};
#[serde(tag = "type")]
enum Message {
    Request(String),
    Response(u8),
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
    #[allow(unused_extern_crates, clippy::useless_attribute)]
    extern crate serde as _serde;
    #[automatically_derived]
    impl<'de> _serde::Deserialize<'de> for Message {
        fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
        where
            __D: _serde::Deserializer<'de>,
        {
            #[allow(non_camel_case_types)]
            enum __Field {
                __field0,
                __field1,
            }
            struct __FieldVisitor;
            impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                type Value = __Field;
                fn expecting(
                    &self,
                    __formatter: &mut _serde::__private::Formatter,
                ) -> _serde::__private::fmt::Result {
                    _serde::__private::Formatter::write_str(__formatter, "variant identifier")
                }
                fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result<Self::Value, __E>
                where
                    __E: _serde::de::Error,
                {
                    match __value {
                        0u64 => _serde::__private::Ok(__Field::__field0),
                        1u64 => _serde::__private::Ok(__Field::__field1),
                        _ => _serde::__private::Err(_serde::de::Error::invalid_value(
                            _serde::de::Unexpected::Unsigned(__value),
                            &"variant index 0 <= i < 2",
                        )),
                    }
                }
                fn visit_str<__E>(
                    self,
                    __value: &str,
                ) -> _serde::__private::Result<Self::Value, __E>
                where
                    __E: _serde::de::Error,
                {
                    match __value {
                        "Request" => _serde::__private::Ok(__Field::__field0),
                        "Response" => _serde::__private::Ok(__Field::__field1),
                        _ => _serde::__private::Err(_serde::de::Error::unknown_variant(
                            __value, VARIANTS,
                        )),
                    }
                }
                fn visit_bytes<__E>(
                    self,
                    __value: &[u8],
                ) -> _serde::__private::Result<Self::Value, __E>
                where
                    __E: _serde::de::Error,
                {
                    match __value {
                        b"Request" => _serde::__private::Ok(__Field::__field0),
                        b"Response" => _serde::__private::Ok(__Field::__field1),
                        _ => {
                            let __value = &_serde::__private::from_utf8_lossy(__value);
                            _serde::__private::Err(_serde::de::Error::unknown_variant(
                                __value, VARIANTS,
                            ))
                        }
                    }
                }
            }
            impl<'de> _serde::Deserialize<'de> for __Field {
                #[inline]
                fn deserialize<__D>(
                    __deserializer: __D,
                ) -> _serde::__private::Result<Self, __D::Error>
                where
                    __D: _serde::Deserializer<'de>,
                {
                    _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
                }
            }
            const VARIANTS: &'static [&'static str] = &["Request", "Response"];
            let __tagged = match _serde::Deserializer::deserialize_any(
                __deserializer,
                _serde::__private::de::TaggedContentVisitor::<__Field>::new(
                    "type",
                    "internally tagged enum Message",
                ),
            ) {
                _serde::__private::Ok(__val) => __val,
                _serde::__private::Err(__err) => {
                    return _serde::__private::Err(__err);
                }
            };
            match __tagged.tag {
                __Field::__field0 => _serde::__private::Result::map(
                    <String as _serde::Deserialize>::deserialize(
                        _serde::__private::de::ContentDeserializer::<__D::Error>::new(
                            __tagged.content,
                        ),
                    ),
                    Message::Request,
                ),
                __Field::__field1 => _serde::__private::Result::map(
                    <u8 as _serde::Deserialize>::deserialize(
                        _serde::__private::de::ContentDeserializer::<__D::Error>::new(
                            __tagged.content,
                        ),
                    ),
                    Message::Response,
                ),
            }
        }
    }
};
#[rustc_main]
pub fn main() -> () {
    extern crate test;
    test::test_main_static(&[])
}
```



We should check for `type` using similar code.


The code generated by `#[ast_serde]` is

```rust

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use swc_common::ast_serde;
#[serde(untagged)]
enum Message {
    #[tag("Request")]
    Request(String),
    #[tag("Response")]
    Response(u8),
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for Message {
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match (&*self,) {
            (&Message::Request(ref __self_0),) => {
                let debug_trait_builder = &mut ::core::fmt::Formatter::debug_tuple(f, "Request");
                let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_0));
                ::core::fmt::DebugTuple::finish(debug_trait_builder)
            }
            (&Message::Response(ref __self_0),) => {
                let debug_trait_builder = &mut ::core::fmt::Formatter::debug_tuple(f, "Response");
                let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_0));
                ::core::fmt::DebugTuple::finish(debug_trait_builder)
            }
        }
    }
}
impl ::core::marker::StructuralPartialEq for Message {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::cmp::PartialEq for Message {
    #[inline]
    fn eq(&self, other: &Message) -> bool {
        {
            let __self_vi = ::core::intrinsics::discriminant_value(&*self);
            let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other);
            if true && __self_vi == __arg_1_vi {
                match (&*self, &*other) {
                    (&Message::Request(ref __self_0), &Message::Request(ref __arg_1_0)) => {
                        (*__self_0) == (*__arg_1_0)
                    }
                    (&Message::Response(ref __self_0), &Message::Response(ref __arg_1_0)) => {
                        (*__self_0) == (*__arg_1_0)
                    }
                    _ => unsafe { ::core::intrinsics::unreachable() },
                }
            } else {
                false
            }
        }
    }
    #[inline]
    fn ne(&self, other: &Message) -> bool {
        {
            let __self_vi = ::core::intrinsics::discriminant_value(&*self);
            let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other);
            if true && __self_vi == __arg_1_vi {
                match (&*self, &*other) {
                    (&Message::Request(ref __self_0), &Message::Request(ref __arg_1_0)) => {
                        (*__self_0) != (*__arg_1_0)
                    }
                    (&Message::Response(ref __self_0), &Message::Response(ref __arg_1_0)) => {
                        (*__self_0) != (*__arg_1_0)
                    }
                    _ => unsafe { ::core::intrinsics::unreachable() },
                }
            } else {
                true
            }
        }
    }
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
    #[allow(unused_extern_crates, clippy::useless_attribute)]
    extern crate serde as _serde;
    #[automatically_derived]
    impl _serde::Serialize for Message {
        fn serialize<__S>(
            &self,
            __serializer: __S,
        ) -> _serde::__private::Result<__S::Ok, __S::Error>
        where
            __S: _serde::Serializer,
        {
            match *self {
                Message::Request(ref __field0) => {
                    _serde::Serialize::serialize(__field0, __serializer)
                }
                Message::Response(ref __field0) => {
                    _serde::Serialize::serialize(__field0, __serializer)
                }
            }
        }
    }
};
impl<'de> serde::Deserialize<'de> for Message {
    #[allow(unreachable_code)]
    fn deserialize<D>(Deserializer: D) -> ::std::result::Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let content = <swc_common::private::serde::de::Content as serde::Deserialize>::deserialize(
            Deserializer,
        )?;
        let ty = swc_common::serializer::Type::deserialize(
            swc_common::private::serde::de::ContentRefDeserializer::<D::Error>::new(&content),
        )?;
        {
            const TAGS: &[&str] = &["Request"];
            if TAGS.contains(&&*ty.ty) {
                return std::result::Result::map(
                    <String as serde::Deserialize>::deserialize(
                        swc_common::private::serde::de::ContentRefDeserializer::<D::Error>::new(
                            &content,
                        ),
                    ),
                    Message::Request,
                );
            }
        }
        {
            const TAGS: &[&str] = &["Response"];
            if TAGS.contains(&&*ty.ty) {
                return std::result::Result::map(
                    <u8 as serde::Deserialize>::deserialize(
                        swc_common::private::serde::de::ContentRefDeserializer::<D::Error>::new(
                            &content,
                        ),
                    ),
                    Message::Response,
                );
            }
        }
        return Err(serde::de::Error::unknown_variant(
            &ty.ty,
            &["Request", "Response"],
        ));
    }
}
#[rustc_main]
pub fn main() -> () {
    extern crate test;
    test::test_main_static(&[])
}
```

Pull request:
perf(es/ast/serde): Make deserialization faster
ast_node:
 - Improve deserialization of enums.

swc_css_ast:
 - Fix compilation issue.

swc_ecma_ast:
 - Update `serde`.

swc_ecma_parser:
 - Fix compilation issue.

swc_estree_ast:
 - Fix serialization.

---

Closes #3159.

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 50f23bb1a3..d777fe04de 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2064,9 +2064,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 
 [[package]]
 name = "serde"
-version = "1.0.132"
+version = "1.0.133"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008"
+checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
 dependencies = [
  "serde_derive",
 ]
@@ -2085,9 +2085,9 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.132"
+version = "1.0.133"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276"
+checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/crates/ast_node/src/enum_deserialize.rs b/crates/ast_node/src/enum_deserialize.rs
index 46d5892e51..22004fd3ea 100644
--- a/crates/ast_node/src/enum_deserialize.rs
+++ b/crates/ast_node/src/enum_deserialize.rs
@@ -1,4 +1,4 @@
-use pmutil::{smart_quote, Quote};
+use pmutil::{q, smart_quote, Quote, SpanExt};
 use swc_macros_common::prelude::*;
 use syn::{
     self,
@@ -35,9 +35,11 @@ pub fn expand(
         _ => unreachable!("expand_enum is called with none-enum item"),
     };
 
+    let mut has_wildcard = false;
+
     let deserialize = {
         let mut all_tags: Punctuated<_, token::Comma> = Default::default();
-        let match_type = data
+        let tag_match_arms = data
             .variants
             .iter()
             .map(|variant| {
@@ -74,102 +76,359 @@ pub fn expand(
                     !tags.is_empty(),
                     "All #[ast_node] enum variants have one or more tag"
                 );
+
+                // TODO: Clean up this code
                 if tags.len() == 1
                     && match tags.first() {
                         Some(Lit::Str(s)) => &*s.value() == "*",
                         _ => false,
                     }
                 {
-                    Quote::new_call_site()
-                        .quote_with(smart_quote!(
-                            Vars {
-                                Enum: &ident,
-                                Variant: &variant.ident,
-                                VariantFieldType: &field_type,
-                            },
-                            {
-                                match std::result::Result::map(
-                                    <VariantFieldType as serde::Deserialize>::deserialize(
-                                        swc_common::private::serde::de::ContentRefDeserializer::<D::Error>::new(
-                                            &content,
-                                        ),
-                                    ),
-                                    Enum::Variant,
-                                ) {
-                                    Ok(v) => return Ok(v),
-                                    Err(err) => return Err(err),
-                                }
-                            }
-                        ))
-                        .parse()
+                    has_wildcard = true;
                 } else {
                     for tag in tags.iter() {
                         all_tags.push(tag.clone());
                     }
-                    Quote::new_call_site()
-                        .quote_with(smart_quote!(
-                            Vars {
-                                Enum: &ident,
-                                Variant: &variant.ident,
-                                VariantFieldType: &field_type,
-                                tags,
-                            },
-                            {
-                                {
-                                    const TAGS: &[&str] = &[tags];
-                                    if TAGS.contains(&&*ty.ty) {
-                                        return std::result::Result::map(
-                                            <VariantFieldType as serde::Deserialize>::deserialize(
-                                                swc_common::private::serde::de::ContentRefDeserializer::<
-                                                    D::Error,
-                                                >::new(
-                                                    &content
-                                                ),
-                                            ),
-                                            Enum::Variant,
-                                        );
-                                    }
+                }
+
+                Arm {
+                    attrs: Default::default(),
+                    pat: q!(
+                        Vars {
+                            Variant: &variant.ident
+                        },
+                        (__TypeVariant::Variant)
+                    )
+                    .parse(),
+                    guard: Default::default(),
+                    fat_arrow_token: variant.ident.span().as_token(),
+                    body: q!(
+                        Vars {
+                            Variant: &variant.ident,
+                            FieldType: field_type,
+                        },
+                        {
+                            swc_common::private::serde::Result::map(
+                                <FieldType as serde::Deserialize>::deserialize(
+                                    swc_common::private::serde::de::ContentDeserializer::<
+                                        __D::Error,
+                                    >::new(__content),
+                                ),
+                                Self::Variant,
+                            )
+                        }
+                    )
+                    .parse(),
+                    comma: Some(variant.ident.span().as_token()),
+                }
+            })
+            .collect::<Vec<Arm>>();
+
+        let tag_expr = {
+            let mut visit_str_arms = vec![];
+            let mut visit_bytes_arms = vec![];
+
+            for variant in &data.variants {
+                let tags = variant
+                    .attrs
+                    .iter()
+                    .filter_map(|attr| -> Option<VariantAttr> {
+                        if !is_attr_name(attr, "tag") {
+                            return None;
+                        }
+                        let tags =
+                            parse2(attr.tokens.clone()).expect("failed to parse #[tag] attribute");
+
+                        Some(tags)
+                    })
+                    .flat_map(|v| v.tags)
+                    .collect::<Punctuated<_, token::Comma>>();
+
+                assert!(
+                    !tags.is_empty(),
+                    "All #[ast_node] enum variants have one or more tag"
+                );
+                let (str_pat, bytes_pat) = {
+                    if tags.len() == 1
+                        && match tags.first() {
+                            Some(Lit::Str(s)) => &*s.value() == "*",
+                            _ => false,
+                        }
+                    {
+                        (
+                            Pat::Wild(PatWild {
+                                attrs: Default::default(),
+                                underscore_token: variant.ident.span().as_token(),
+                            }),
+                            Pat::Wild(PatWild {
+                                attrs: Default::default(),
+                                underscore_token: variant.ident.span().as_token(),
+                            }),
+                        )
+                    } else {
+                        fn make_pat(lit: Lit) -> (Pat, Pat) {
+                            let s = match lit.clone() {
+                                Lit::Str(s) => s.value().clone(),
+                                _ => {
+                                    unreachable!()
                                 }
+                            };
+                            (
+                                Pat::Lit(PatLit {
+                                    attrs: Default::default(),
+                                    expr: Box::new(Expr::Lit(ExprLit {
+                                        attrs: Default::default(),
+                                        lit: lit.clone(),
+                                    })),
+                                }),
+                                Pat::Lit(PatLit {
+                                    attrs: Default::default(),
+                                    expr: Box::new(Expr::Lit(ExprLit {
+                                        attrs: Default::default(),
+                                        lit: Lit::ByteStr(LitByteStr::new(
+                                            s.as_bytes(),
+                                            call_site(),
+                                        )),
+                                    })),
+                                }),
+                            )
+                        }
+                        if tags.len() == 1 {
+                            make_pat(tags.first().unwrap().clone())
+                        } else {
+                            let mut str_cases = Punctuated::new();
+                            let mut bytes_cases = Punctuated::new();
+
+                            for tag in tags {
+                                let (str_pat, bytes_pat) = make_pat(tag.clone());
+                                str_cases.push(str_pat);
+                                bytes_cases.push(bytes_pat);
                             }
+
+                            (
+                                Pat::Or(PatOr {
+                                    attrs: Default::default(),
+                                    leading_vert: Default::default(),
+                                    cases: str_cases,
+                                }),
+                                Pat::Or(PatOr {
+                                    attrs: Default::default(),
+                                    leading_vert: Default::default(),
+                                    cases: bytes_cases,
+                                }),
+                            )
+                        }
+                    }
+                };
+                visit_str_arms.push(Arm {
+                    attrs: Default::default(),
+                    pat: str_pat,
+                    guard: None,
+                    fat_arrow_token: variant.ident.span().as_token(),
+                    body: q!(
+                        Vars {
+                            Variant: &variant.ident,
+                        },
+                        { Ok(__TypeVariant::Variant) }
+                    )
+                    .parse(),
+                    comma: Some(variant.ident.span().as_token()),
+                });
+                visit_bytes_arms.push(Arm {
+                    attrs: Default::default(),
+                    pat: bytes_pat,
+                    guard: None,
+                    fat_arrow_token: variant.ident.span().as_token(),
+                    body: q!(
+                        Vars {
+                            Variant: &variant.ident,
+                        },
+                        { Ok(__TypeVariant::Variant) }
+                    )
+                    .parse(),
+                    comma: Some(variant.ident.span().as_token()),
+                });
+            }
+
+            if !has_wildcard {
+                visit_str_arms.push(Arm {
+                    attrs: Default::default(),
+                    pat: Pat::Wild(PatWild {
+                        attrs: Default::default(),
+                        underscore_token: ident.span().as_token(),
+                    }),
+                    guard: None,
+                    fat_arrow_token: ident.span().as_token(),
+                    body: q!({
+                        swc_common::private::serde::Err(serde::de::Error::unknown_variant(
+                            __value, VARIANTS,
                         ))
-                        .parse()
-                }
-            })
-            .collect::<Vec<Expr>>();
+                    })
+                    .parse(),
+                    comma: Some(ident.span().as_token()),
+                });
+                visit_bytes_arms.push(Arm {
+                    attrs: Default::default(),
+                    pat: Pat::Wild(PatWild {
+                        attrs: Default::default(),
+                        underscore_token: ident.span().as_token(),
+                    }),
+                    guard: None,
+                    fat_arrow_token: ident.span().as_token(),
+                    body: q!({
+                        {
+                            let __value = &swc_common::private::serde::from_utf8_lossy(__value);
+                            swc_common::private::serde::Err(serde::de::Error::unknown_variant(
+                                __value, VARIANTS,
+                            ))
+                        }
+                    })
+                    .parse(),
+                    comma: Some(ident.span().as_token()),
+                });
+            }
+
+            let visit_str_body = Expr::Match(ExprMatch {
+                attrs: Default::default(),
+                match_token: call_site(),
+                expr: q!((__value)).parse(),
+                brace_token: call_site(),
+                arms: visit_str_arms,
+            });
+            let visit_bytes_body = Expr::Match(ExprMatch {
+                attrs: Default::default(),
+                match_token: call_site(),
+                expr: q!((__value)).parse(),
+                brace_token: call_site(),
+                arms: visit_bytes_arms,
+            });
+
+            q!(
+                Vars {
+                    visit_str_body,
+                    visit_bytes_body,
+                    all_tags: &all_tags,
+                },
+                {
+                    {
+                        static VARIANTS: &[&str] = &[all_tags];
+
+                        struct __TypeVariantVisitor;
+
+                        impl<'de> serde::de::Visitor<'de> for __TypeVariantVisitor {
+                            type Value = __TypeVariant;
+                            fn expecting(
+                                &self,
+                                __formatter: &mut swc_common::private::serde::Formatter,
+                            ) -> swc_common::private::serde::fmt::Result
+                            {
+                                swc_common::private::serde::Formatter::write_str(
+                                    __formatter,
+                                    "variant identifier",
+                                )
+                            }
 
-        let mut match_type_expr = Quote::new_call_site();
-        for expr in match_type {
-            match_type_expr = match_type_expr.quote_with(smart_quote!(Vars { expr }, { expr }));
-        }
+                            fn visit_str<__E>(
+                                self,
+                                __value: &str,
+                            ) -> swc_common::private::serde::Result<Self::Value, __E>
+                            where
+                                __E: serde::de::Error,
+                            {
+                                visit_str_body
+                            }
+
+                            fn visit_bytes<__E>(
+                                self,
+                                __value: &[u8],
+                            ) -> swc_common::private::serde::Result<Self::Value, __E>
+                            where
+                                __E: serde::de::Error,
+                            {
+                                visit_bytes_body
+                            }
+                        }
+
+                        impl<'de> serde::Deserialize<'de> for __TypeVariant {
+                            #[inline]
+                            fn deserialize<__D>(
+                                __deserializer: __D,
+                            ) -> swc_common::private::serde::Result<Self, __D::Error>
+                            where
+                                __D: serde::Deserializer<'de>,
+                            {
+                                serde::Deserializer::deserialize_identifier(
+                                    __deserializer,
+                                    __TypeVariantVisitor,
+                                )
+                            }
+                        }
 
-        match_type_expr = match_type_expr.quote_with(smart_quote!(Vars { all_tags }, {
-            return Err(serde::de::Error::unknown_variant(&ty.ty, &[all_tags]));
-        }));
+                        let ty = swc_common::serializer::Type::deserialize(
+                            swc_common::private::serde::de::ContentRefDeserializer::<__D::Error>::new(
+                                &__content,
+                            ),
+                        )?;
 
+                        let __tagged = __TypeVariant::deserialize(
+                            swc_common::private::serde::de::ContentDeserializer::<__D::Error>::new(
+                                swc_common::private::serde::de::Content::Str(&ty.ty),
+                            )
+                        )?;
+
+                        __tagged
+                    }
+                }
+            )
+            .parse::<Expr>()
+        };
+
+        let match_type_expr = Expr::Match(ExprMatch {
+            attrs: Default::default(),
+            match_token: call_site(),
+            expr: q!({ __tagged }).parse(),
+            brace_token: call_site(),
+            arms: tag_match_arms,
+        });
+
+        let variants: Punctuated<Variant, Token![,]> = {
+            data.variants
+                .iter()
+                .cloned()
+                .map(|variant| Variant {
+                    attrs: Default::default(),
+                    fields: Fields::Unit,
+                    ..variant
+                })
+                .collect()
+        };
         Quote::new_call_site()
             .quote_with(smart_quote!(
                 Vars {
                     match_type_expr,
-                    Enum: &ident
+                    Enum: &ident,
+                    tag_expr,
+                    variants
                 },
                 {
                     impl<'de> serde::Deserialize<'de> for Enum {
                         #[allow(unreachable_code)]
-                        fn deserialize<D>(Deserializer: D) -> ::std::result::Result<Self, D::Error>
+                        fn deserialize<__D>(
+                            __deserializer: __D,
+                        ) -> ::std::result::Result<Self, __D::Error>
                         where
-                            D: serde::Deserializer<'de>,
+                            __D: serde::Deserializer<'de>,
                         {
-                            let content =
-                                <swc_common::private::serde::de::Content as serde::Deserialize>::deserialize(
-                                    Deserializer,
-                                )?;
-
-                            let ty = swc_common::serializer::Type::deserialize(
-                                swc_common::private::serde::de::ContentRefDeserializer::<D::Error>::new(
-                                    &content,
-                                ),
+                            enum __TypeVariant {
+                                variants,
+                            }
+
+                            let __content = <swc_common::private::serde::de::Content as serde::Deserialize>::deserialize(
+                                __deserializer,
                             )?;
 
+                            let __tagged = tag_expr;
+
                             match_type_expr
                         }
                     }
diff --git a/crates/swc_common/src/lib.rs b/crates/swc_common/src/lib.rs
index 13c0d3d0d1..3cbbf386a5 100644
--- a/crates/swc_common/src/lib.rs
+++ b/crates/swc_common/src/lib.rs
@@ -28,6 +28,7 @@
 //! Allows replacing operations related to thread-local variables with a trait.
 #![deny(unused)]
 #![cfg_attr(docsrs, feature(doc_cfg))]
+
 pub use self::{
     eq::{EqIgnoreSpan, TypeEq},
     errors::{SourceMapper, SourceMapperDyn},
diff --git a/crates/swc_css_ast/src/lib.rs b/crates/swc_css_ast/src/lib.rs
index d9c6e863f1..cdfac379a7 100644
--- a/crates/swc_css_ast/src/lib.rs
+++ b/crates/swc_css_ast/src/lib.rs
@@ -22,9 +22,9 @@ pub enum Rule {
     #[tag("QualifiedRule")]
     QualifiedRule(QualifiedRule),
 
-    #[tag("*")]
-    AtRule(AtRule),
-
     #[tag("Tokens")]
     Invalid(Tokens),
+
+    #[tag("*")]
+    AtRule(AtRule),
 }
diff --git a/crates/swc_ecma_ast/Cargo.toml b/crates/swc_ecma_ast/Cargo.toml
index 9a60de0379..bfa1f9ec61 100644
--- a/crates/swc_ecma_ast/Cargo.toml
+++ b/crates/swc_ecma_ast/Cargo.toml
@@ -20,7 +20,7 @@ fuzzing = ["arbitrary", "swc_common/arbitrary"]
 arbitrary = {version = "1", optional = true, features = ["derive"]}
 is-macro = "0.1"
 num-bigint = {version = "0.2", features = ["serde"]}
-serde = {version = "1.0.88", features = ["derive"]}
+serde = {version = "1.0.133", features = ["derive"]}
 string_enum = {version = "0.3.1", path = "../string_enum"}
 swc_atoms = {version = "0.2", path = "../swc_atoms"}
 swc_common = {version = "0.15.0", path = "../swc_common"}
diff --git a/crates/swc_ecma_parser/src/parser/expr.rs b/crates/swc_ecma_parser/src/parser/expr.rs
index 228887073b..f1c3633b41 100644
--- a/crates/swc_ecma_parser/src/parser/expr.rs
+++ b/crates/swc_ecma_parser/src/parser/expr.rs
@@ -1561,10 +1561,10 @@ impl<'a, I: Tokens> Parser<I> {
 
 #[ast_node]
 pub(in crate::parser) enum PatOrExprOrSpread {
+    #[tag("ExprOrSpread")]
+    ExprOrSpread(ExprOrSpread),
     #[tag("*")]
     Pat(Pat),
-    #[tag("*")]
-    ExprOrSpread(ExprOrSpread),
 }
 
 /// simple leaf methods.
diff --git a/crates/swc_ecma_plugin_ast/Cargo.toml b/crates/swc_ecma_plugin_ast/Cargo.toml
index 9c9e5bc1c9..e2eb330509 100644
--- a/crates/swc_ecma_plugin_ast/Cargo.toml
+++ b/crates/swc_ecma_plugin_ast/Cargo.toml
@@ -18,7 +18,7 @@ swc_common = {version = "0.15.0", path = "../swc_common", features = ["plugin-ba
 swc_ecma_ast = {version = "0.60.0", path = "../swc_ecma_ast/"}
 
 [dev-dependencies]
-serde = "1"
+serde = "1.0.133"
 serde_json = "1"
 swc_ecma_parser = {version = "0.82.0", path = "../swc_ecma_parser"}
 swc_node_base = {version = "0.5.1", path = "../swc_node_base"}
diff --git a/crates/swc_ecma_plugin_ast/benches/comp.rs b/crates/swc_ecma_plugin_ast/benches/comp.rs
index 0133462cf5..591ad9f3aa 100644
--- a/crates/swc_ecma_plugin_ast/benches/comp.rs
+++ b/crates/swc_ecma_plugin_ast/benches/comp.rs
@@ -45,6 +45,8 @@ fn json_deserialize(b: &mut Bencher) {
     let program = input();
     let json_str = serde_json::to_string(&program).unwrap();
 
+    eprintln!("json: {}", json_str);
+
     b.iter(|| {
         let v: Program = serde_json::from_str(&json_str).unwrap();
         black_box(v);
diff --git a/crates/swc_estree_ast/src/flow.rs b/crates/swc_estree_ast/src/flow.rs
index 2e1f73cf97..81436d8675 100644
--- a/crates/swc_estree_ast/src/flow.rs
+++ b/crates/swc_estree_ast/src/flow.rs
@@ -220,7 +220,7 @@ pub enum FlowDeclaration {
     DeclareOpaqueType(DeclareOpaqueType),
     #[tag("DeclareVariable")]
     Var(DeclareVariable),
-    #[tag("DeclareExportAllDeclaration")]
+    #[tag("DeclareExportDeclaration")]
     ExportDecl(DeclareExportDeclaration),
     #[tag("DeclareExportAllDeclaration")]
     ExportAllDecl(DeclareExportAllDeclaration),
diff --git a/rust-toolchain b/rust-toolchain
index 1307a1c398..d222b5df20 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,1 +1,1 @@
-nightly-2021-11-15
\ No newline at end of file
+nightly-2021-12-21
\ No newline at end of file


Test patch:
diff --git a/crates/swc_common/tests/issue_3159.rs b/crates/swc_common/tests/issue_3159.rs
new file mode 100644
index 0000000000..be23d46b68
--- /dev/null
+++ b/crates/swc_common/tests/issue_3159.rs
@@ -0,0 +1,9 @@
+use swc_common::ast_serde;
+
+#[ast_serde]
+enum Message {
+    #[tag("Request")]
+    Request(String),
+    #[tag("Response")]
+    Response(u8),
+}