Repository: tokio-rs/axum
File: axum-macros/src/debug_handler.rs (Rust)

Code before:
                    #call_check_fn_body
                }
            }
        })
        .collect::<TokenStream>()
}

///If the output is a tuple with 2 or more elements,
/// it checks with the following pattern,
/// first element => StatusCode || Parts || IntoResponseParts
///last element => IntoResponse
///other elements => IntoResponseParts
///the max numbers of IntoResponseParts(16)
fn check_output_tuples(item_fn: &ItemFn) -> Option<TokenStream> {
    //Extract tuple types
    let elements = match &item_fn.sig.output {
        ReturnType::Type(_, ty) => match &**ty {
            Type::Tuple(tuple) => &tuple.elems,
            _ => return None,
        },
        _ => return None,
    };

    if elements.len() < 2 {
        return None;
    }
    //Amount of IntoRequestParts
    let mut parts_amount: i8 = 0;

    let token_stream = WithPosition::new(elements.iter())
        .enumerate()
        .map(|(_idx, arg)| match &arg {
            //First element type in the tuple
            Position::First(ty) => {
                let typename = extract_clean_typename(ty);
                if typename.is_none() {
                    quote! {}
                } else {
                    let typename = typename.unwrap();
                    match &*typename.to_string() {
                        "Parts" => quote! {},
                        "Response" => quote! {},
                        "StatusCode" => {
                            quote! {}
                        }
                        _ => {
                            parts_amount += 1;
                            check_into_response_parts(ty, parts_amount)
                        }
                    }
                }

Review comment (suggestion):
This this special case? What if the return type is `(String,)`, its a bit exotic but if it doesn't require much special casing then it would be cool to support.

Code after:
                #[doc(hidden)]
                fn #call_check_fn() {
                    #call_check_fn_body
                }
            }
        })
        .collect::<TokenStream>()
}

fn check_output_tuples(item_fn: &ItemFn) -> TokenStream {
    let elems = match &item_fn.sig.output {
        ReturnType::Type(_, ty) => match &**ty {
            Type::Tuple(tuple) => &tuple.elems,
            _ => return quote! {},
        },
        ReturnType::Default => return quote! {},
    };

    let handler_ident = &item_fn.sig.ident;

    match elems.len() {
        0 => quote! {},
        n if n > 17 => syn::Error::new_spanned(
            &item_fn.sig.output,
            "Cannot return tuples with more than 17 elements",
        )
        .to_compile_error(),
        _ => WithPosition::new(elems)
            .enumerate()
            .map(|(idx, arg)| match arg {
                Position::First(ty) => match extract_clean_typename(ty).as_deref() {
                    Some("StatusCode" | "Response") => quote! {},
                    Some("Parts") => check_is_response_parts(ty, handler_ident, idx),
                    Some(_) | None => {
                        if let Some(tn) = well_known_last_response_type(ty) {
                            syn::Error::new_spanned(
                                ty,
                                format!(
                                    "`{tn}` must be the last element \
                                    in a response tuple"
                                ),
                            )
                            .to_compile_error()
                        } else {
                            check_into_response_parts(ty, handler_ident, idx)
                        }
                    }
                },
                Position::Middle(ty) => {
                    if let Some(tn) = well_known_last_response_type(ty) {
                        syn::Error::new_spanned(