Repository: serde-rs/serde
File: serde_derive/src/de.rs (Rust)

Code before:
    );
    let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg);

    quote_block! {
        let __content = try!(<_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer));

        #(
            if let _serde::__private::Ok(__ok) = #attempts {
                return _serde::__private::Ok(__ok);
            }
        )*

        _serde::__private::Err(_serde::de::Error::custom(#fallthrough_msg))
    }
}

fn deserialize_externally_tagged_variant(
    params: &Parameters,
    variant: &Variant,
    cattrs: &attr::Container,
) -> Fragment {
    if let Some(path) = variant.attrs.deserialize_with() {
        let (wrapper, wrapper_ty, unwrap_fn) = wrap_deserialize_variant_with(params, variant, path);
        return quote_block! {
            #wrapper
            _serde::__private::Result::map(
                _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), #unwrap_fn)
        };
    }

    let variant_ident = &variant.ident;

    match variant.style {
        Style::Unit => {
            let this_value = &params.this_value;
            quote_block! {
                try!(_serde::de::VariantAccess::unit_variant(__variant));
                _serde::__private::Ok(#this_value::#variant_ident)
            }
        }
        Style::Newtype => deserialize_externally_tagged_newtype_variant(
            variant_ident,
            params,
            &variant.fields[0],
            cattrs,
        ),
        Style::Tuple => {
            deserialize_tuple(Some(variant_ident), params, &variant.fields, cattrs, None)
        }
        Style::Struct => deserialize_struct(
            Some(variant_ident),

Review comment (suggestion):
```suggestion
    let attempts = first_attempt(deserializer)
```

the last use can consume it.

Code after:
    variants: &[Variant],
    cattrs: &attr::Container,
) -> Fragment {
    deserialize_untagged_enum_after(params, variants, cattrs, |_| None)
}

fn deserialize_untagged_enum_after(
    params: &Parameters,
    variants: &[Variant],
    cattrs: &attr::Container,
    first_attempt: impl FnOnce(TokenStream) -> Option<Expr>,
) -> Fragment {
    let deserializer =
        quote!(_serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content));
    let attempts = variants
        .iter()
        .filter(|variant| !variant.attrs.skip_deserializing())
        .map(|variant| {
            Expr(deserialize_untagged_variant(
                params,
                variant,
                cattrs,
                deserializer.clone(),
            ))
        });
    let attempts = first_attempt(deserializer.clone())
        .into_iter()
        .chain(attempts);
    // TODO this message could be better by saving the errors from the failed
    // attempts. The heuristic used by TOML was to count the number of fields
    // processed before an error, and use the error that happened after the
    // largest number of fields. I'm not sure I like that. Maybe it would be
    // better to save all the errors and combine them into one message that
    // explains why none of the variants matched.
    let fallthrough_msg = format!(
        "data did not match any variant of untagged enum {}",
        params.type_name()
    );
    let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg);

    quote_block! {
        let __content = try!(<_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer));

        #(
            if let _serde::__private::Ok(__ok) = #attempts {
                return _serde::__private::Ok(__ok);
            }
        )*

        _serde::__private::Err(_serde::de::Error::custom(#fallthrough_msg))
    }