Repository: pydantic/pydantic
Issue category: Feature Request

Support async functions with `@validate_call` decorator
### Initial Checks

- [X] I confirm that I'm using Pydantic V2

### Description

I'm writing a project using `asgiref`.

When I use `async_to_sync`, I got a error ` UserWarning: async_to_sync was passed a non-async-marked callable`.

I think it's due to `@validate_call` decorator because it's not appear if i delete `@validate_call`.

For example, here is a simple code. The correct output is `True` but actual output is `False`.  How can we fix this bug?

### Example Code

```Python
import asyncio
import inspect

from pydantic import validate_call


@validate_call(validate_return=True)
async def delay_number(n: int) -> int:
    await asyncio.sleep(1)
    return n


if __name__ == "__main__":
    print(inspect.iscoroutinefunction(delay_number))
```


### Python, Pydantic & OS Version

```Text
pydantic version: 2.9.1
        pydantic-core version: 2.23.3
          pydantic-core build: profile=release pgo=false
                 install path: C:\Users\movis\miniconda3\envs\volans_env\Lib\site-packages\pydantic
               python version: 3.11.9 | packaged by Anaconda, Inc. | (main, Apr 19 2024, 16:40:41) [MSC v.1916 64 bit (AMD64)]
                     platform: Windows-10-10.0.22631-SP0
             related packages: fastapi-0.112.4 typing_extensions-4.12.2
                       commit: unknown
```



Functions to edit:
pydantic/validate_call_decorator.py:validate_call

Patch:
diff --git a/pydantic/validate_call_decorator.py b/pydantic/validate_call_decorator.py
index fef84af912..509a7463c5 100644
--- a/pydantic/validate_call_decorator.py
+++ b/pydantic/validate_call_decorator.py
@@ -3,6 +3,7 @@
 from __future__ import annotations as _annotations
 
 import functools
+import inspect
 from typing import TYPE_CHECKING, Any, Callable, TypeVar, overload
 
 from ._internal import _typing_extra, _validate_call
@@ -55,12 +56,18 @@ def validate(function: AnyCallableT) -> AnyCallableT:
 
         validate_call_wrapper = _validate_call.ValidateCallWrapper(function, config, validate_return, local_ns)
 
-        @functools.wraps(function)
-        def wrapper_function(*args, **kwargs):
-            return validate_call_wrapper(*args, **kwargs)
+        if inspect.iscoroutinefunction(function):
 
-        wrapper_function.raw_function = function  # type: ignore
+            @functools.wraps(function)
+            async def wrapper_function(*args, **kwargs):  # type: ignore
+                return await validate_call_wrapper(*args, **kwargs)
+        else:
+
+            @functools.wraps(function)
+            def wrapper_function(*args, **kwargs):
+                return validate_call_wrapper(*args, **kwargs)
 
+        wrapper_function.raw_function = function  # type: ignore
         return wrapper_function  # type: ignore
 
     if func:

Test patch: diff --git a/tests/test_validate_call.py b/tests/test_validate_call.py
index 12547f5a4f..e0a10504c9 100644
--- a/tests/test_validate_call.py
+++ b/tests/test_validate_call.py
@@ -292,6 +292,9 @@ async def run():
         v = await foo(1, 2)
         assert v == 'a=1 b=2'
 
+    # insert_assert(inspect.iscoroutinefunction(foo) is True)
+    assert inspect.iscoroutinefunction(foo) is True
+
     asyncio.run(run())
     with pytest.raises(ValidationError) as exc_info:
         asyncio.run(foo('x'))