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

Code before:
use std::{collections::HashSet, fmt};

use crate::{
    attr_parsing::{parse_assignment_attribute, second},
    with_position::{Position, WithPosition},
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, quote_spanned};
use syn::{parse::Parse, spanned::Spanned, FnArg, ItemFn, ReturnType, Token, Type};

// I'm not sure how to make [`ItemFn`] be passed by reference without causing errors...
#[allow(clippy::needless_pass_by_value)]
pub(crate) fn expand(attr: Attrs, item_fn: ItemFn, kind: FunctionKind) -> TokenStream {
    let Attrs { state_ty } = attr;

    let mut state_ty = state_ty.map(second);

    let check_extractor_count = check_extractor_count(&item_fn, kind);
    let check_path_extractor = check_path_extractor(&item_fn, kind);
    let check_output_tuples = check_output_tuples(&item_fn);
    let check_output_impls_into_response = if check_output_tuples.is_empty() {
        check_output_impls_into_response(&item_fn)
    } else {
        check_output_tuples
    };

    // If the function is generic, we can't reliably check its inputs or whether the future it
    // returns is `Send`. Skip those checks to avoid unhelpful additional compiler errors.
    let check_inputs_and_future_send = if item_fn.sig.generics.params.is_empty() {
        let mut err = None;

        if state_ty.is_none() {
            let state_types_from_args = state_types_from_args(&item_fn);

            #[allow(clippy::comparison_chain)]
            if state_types_from_args.len() == 1 {
                state_ty = state_types_from_args.into_iter().next();

Review comment (suggestion):
[This](https://github.com/mladedav/axum/commit/5426b806e60e9d737b76b860c66758f1eed53e54) seems to work for me or am I missing something?

For the record this seems fine, changing the other one feels like a downgrade due to the change to the callsite.

I'd be fine with keeping `allow` for both of these, but I'll let you decide, what you like more.

Code after:
use std::{collections::HashSet, fmt};

use crate::{
    attr_parsing::{parse_assignment_attribute, second},
    with_position::{Position, WithPosition},
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, quote_spanned};
use syn::{parse::Parse, spanned::Spanned, FnArg, ItemFn, ReturnType, Token, Type};

pub(crate) fn expand(attr: Attrs, item_fn: &ItemFn, kind: FunctionKind) -> TokenStream {
    let Attrs { state_ty } = attr;

    let mut state_ty = state_ty.map(second);

    let check_extractor_count = check_extractor_count(item_fn, kind);
    let check_path_extractor = check_path_extractor(item_fn, kind);
    let check_output_tuples = check_output_tuples(item_fn);
    let check_output_impls_into_response = if check_output_tuples.is_empty() {
        check_output_impls_into_response(item_fn)
    } else {
        check_output_tuples
    };

    // If the function is generic, we can't reliably check its inputs or whether the future it
    // returns is `Send`. Skip those checks to avoid unhelpful additional compiler errors.
    let check_inputs_and_future_send = if item_fn.sig.generics.params.is_empty() {
        let mut err = None;

        if state_ty.is_none() {
            let state_types_from_args = state_types_from_args(item_fn);

            #[allow(clippy::comparison_chain)]
            if state_types_from_args.len() == 1 {
                state_ty = state_types_from_args.into_iter().next();
            } else if state_types_from_args.len() > 1 {
                err = Some(