#[macro_export]
#[doc(hidden)]
macro_rules! impl_selectable_expression {
    ($struct_name:ident) => {
        impl_selectable_expression!(ty_params = (), struct_ty = $struct_name,);
    };
    ($struct_name:ident<$($ty_params:ident),+>) => {
        impl_selectable_expression!(
            ty_params = ($($ty_params),+),
            struct_ty = $struct_name<$($ty_params),+>,
        );
    };
    (ty_params = ($($ty_params:ident),*), struct_ty = $struct_ty:ty,) => {
        impl<$($ty_params,)* QS> $crate::expression::SelectableExpression<QS>
            for $struct_ty where
                $struct_ty: $crate::expression::AppearsOnTable<QS>,
                $($ty_params: $crate::expression::SelectableExpression<QS>,)*
        {
        }
        impl<$($ty_params,)* QS> $crate::expression::AppearsOnTable<QS>
            for $struct_ty where
                $struct_ty: $crate::expression::Expression,
                $($ty_params: $crate::expression::AppearsOnTable<QS>,)*
        {
        }
    };
}
#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_parse_type_args {
    
    
    
    
    (
        data = $data:tt,
        callback = $callback:ident,
        tokens = $tokens:tt,
    ) => {
        __diesel_parse_type_args! {
            data = $data,
            callback = $callback,
            args = (),
            bounds = (),
            tokens = $tokens,
        }
    };
    
    
    
    
    
    
    
    (
        data = $data:tt,
        callback = $callback:ident,
        args = ($($args:tt)*),
        bounds = ($($bounds:tt)*),
        tokens = ($next_arg:ident : $($tokens:tt)*),
    ) => {
        __diesel_parse_type_args! {
            brackets = (),
            data = $data,
            callback = $callback,
            args = ($($args)* $next_arg,),
            bounds = ($($bounds)* $next_arg:),
            tokens = ($($tokens)*),
        }
    };
    
    
    
    
    
    (
        data = $data:tt,
        callback = $callback:ident,
        args = ($($args:tt)*),
        bounds = ($($bounds:tt)*),
        tokens = ($next_arg:ident $($tokens:tt)*),
    ) => {
        __diesel_parse_type_args! {
            data = $data,
            callback = $callback,
            args = ($($args)* $next_arg,),
            bounds = ($($bounds)* $next_arg,),
            tokens = ($($tokens)*),
        }
    };
    
    
    
    
    
    (
        brackets = (),
        data = $data:tt,
        callback = $callback:ident,
        args = $args:tt,
        bounds = ($($bounds:tt)*),
        tokens = (> $($tokens:tt)*),
    ) => {
        __diesel_parse_type_args! {
            data = $data,
            callback = $callback,
            args = $args,
            bounds = ($($bounds)*,),
            tokens = (> $($tokens)*),
        }
    };
    
    
    
    
    
    (
        brackets = (),
        data = $data:tt,
        callback = $callback:ident,
        args = $args:tt,
        bounds = ($($bounds:tt)*),
        tokens = (, $($tokens:tt)*),
    ) => {
        __diesel_parse_type_args! {
            data = $data,
            callback = $callback,
            args = $args,
            bounds = ($($bounds)* ,),
            tokens = ($($tokens)*),
        }
    };
    
    
    
    
    
    
    (
        brackets = ($($brackets:tt)*),
        data = $data:tt,
        callback = $callback:ident,
        args = $args:tt,
        bounds = ($($bounds:tt)*),
        tokens = (< $($tokens:tt)*),
    ) => {
        __diesel_parse_type_args! {
            brackets = (< $($brackets)*),
            data = $data,
            callback = $callback,
            args = $args,
            bounds = ($($bounds)* <),
            tokens = ($($tokens)*),
        }
    };
    
    
    
    
    
    (
        brackets = (< $($brackets:tt)*),
        data = $data:tt,
        callback = $callback:ident,
        args = $args:tt,
        bounds = ($($bounds:tt)*),
        tokens = (>> $($tokens:tt)*),
    ) => {
        __diesel_parse_type_args! {
            brackets = ($($brackets)*),
            data = $data,
            callback = $callback,
            args = $args,
            bounds = ($($bounds)* >),
            tokens = (> $($tokens)*),
        }
    };
    
    
    
    
    
    
    
    (
        brackets = (< $($brackets:tt)*),
        data = $data:tt,
        callback = $callback:ident,
        args = $args:tt,
        bounds = ($($bounds:tt)*),
        tokens = (> $($tokens:tt)*),
    ) => {
        __diesel_parse_type_args! {
            brackets = ($($brackets)*),
            data = $data,
            callback = $callback,
            args = $args,
            bounds = ($($bounds)* >),
            tokens = ($($tokens)*),
        }
    };
    
    
    
    
    
    
    (
        brackets = $brackets:tt,
        data = $data:tt,
        callback = $callback:ident,
        args = $args:tt,
        bounds = ($($bounds:tt)*),
        tokens = ($token:tt $($tokens:tt)*),
    ) => {
        __diesel_parse_type_args! {
            brackets = $brackets,
            data = $data,
            callback = $callback,
            args = $args,
            bounds = ($($bounds)* $token),
            tokens = ($($tokens)*),
        }
    };
    
    
    
    
    
    (
        data = $data:tt,
        callback = $callback:ident,
        args = $args:tt,
        bounds = $bounds:tt,
        tokens = (, $($tokens:tt)*),
    ) => {
        __diesel_parse_type_args! {
            data = $data,
            callback = $callback,
            args = $args,
            bounds = $bounds,
            tokens = ($($tokens)*),
        }
    };
    
    
    
    (
        data = $data:tt,
        callback = $callback:ident,
        args = $args:tt,
        bounds = $bounds:tt,
        tokens = (> $($tokens:tt)*),
    ) => {
        $callback! {
            data = $data,
            type_args = $args,
            type_args_with_bounds = $bounds,
            unparsed_tokens = ($($tokens)*),
        }
    };
}
#[test]
fn parse_type_args_empty() {
    let expected = stringify!(
        data = (),
        type_args = (),
        type_args_with_bounds = (),
        unparsed_tokens = (),
    );
    let actual = __diesel_parse_type_args! {
        data = (),
        callback = stringify,
        tokens = (>),
    };
    assert_eq!(expected, actual);
}
#[test]
fn parse_type_args_simple() {
    let expected = stringify!(
        data = (foo),
        type_args = (T,),
        type_args_with_bounds = (T,),
        unparsed_tokens = (),
    );
    let actual = __diesel_parse_type_args! {
        data = (foo),
        callback = stringify,
        tokens = (T>),
    };
    assert_eq!(expected, actual);
    let actual = __diesel_parse_type_args! {
        data = (foo),
        callback = stringify,
        tokens = (T,>),
    };
    assert_eq!(expected, actual);
}
#[test]
fn parse_type_args_multiple() {
    let expected = stringify!(
        data = (foo),
        type_args = (T, U,),
        type_args_with_bounds = (T, U,),
        unparsed_tokens = (),
    );
    let actual = __diesel_parse_type_args! {
        data = (foo),
        callback = stringify,
        tokens = (T,U>),
    };
    assert_eq!(expected, actual);
    let actual = __diesel_parse_type_args! {
        data = (foo),
        callback = stringify,
        tokens = (T,U,>),
    };
    assert_eq!(expected, actual);
}
#[test]
fn parse_type_args_with_bounds() {
    let expected = stringify!(
        data = (foo),
        type_args = (T, U,),
        type_args_with_bounds = (T: Foo + Bar, U: Baz,),
        unparsed_tokens = (),
    );
    let actual = __diesel_parse_type_args! {
        data = (foo),
        callback = stringify,
        tokens = (T: Foo + Bar, U: Baz>),
    };
    assert_eq!(expected, actual);
    let actual = __diesel_parse_type_args! {
        data = (foo),
        callback = stringify,
        tokens = (T: Foo + Bar, U: Baz,>),
    };
    assert_eq!(expected, actual);
}
#[test]
fn parse_type_args_with_bounds_containing_braces_and_commas() {
    let expected = stringify!(
        data = (foo),
        type_args = (T,U,),
        type_args_with_bounds = (T: Foo<X> + Bar<U, V>,U: Baz<Vec<i32>, String>,),
        unparsed_tokens = (),
    );
    let actual = __diesel_parse_type_args! {
        data = (foo),
        callback = stringify,
        tokens = (T: Foo<X> + Bar<U, V>,U: Baz<Vec<i32>, String>>),
    };
    assert_eq!(expected, actual);
    let actual = __diesel_parse_type_args! {
        data = (foo),
        callback = stringify,
        tokens = (T: Foo<X> + Bar<U, V>,U: Baz<Vec<i32>, String>,>),
    };
    assert_eq!(expected, actual);
}
#[test]
fn parse_type_args_with_trailer() {
    let expected = stringify!(
        data = (
            meta = (#[aggregate]),
            fn_name = max,
        ),
        type_args = (ST,),
        type_args_with_bounds = (ST: SqlOrd + IntoNullable,),
        unparsed_tokens = ((expr: ST) -> ST::Nullable),
    );
    let actual = __diesel_parse_type_args! {
        data = (
            meta = (#[aggregate]),
            fn_name = max,
        ),
        callback = stringify,
        tokens = (ST: SqlOrd + IntoNullable>(expr: ST) -> ST::Nullable),
    };
    assert_eq!(expected, actual);
}
#[test]
fn parse_type_args_with_existentials_and_lifetimes() {
    let expected = stringify! (
        data = (),
        type_args = (ST,U,),
        type_args_with_bounds = (ST: for<'a> Foo<'a, U> + 'static, U,),
        unparsed_tokens = (),
    );
    let actual = __diesel_parse_type_args! {
        data = (),
        callback = stringify,
        tokens = (ST: for<'a> Foo<'a, U> + 'static, U>),
    };
    assert_eq!(expected, actual);
}