Repository: Rapptz/discord.py

Issue:
Python 3.10 Union syntax breaks when used with commands.Range
### Summary

title

### Reproduction Steps

annotate a commmand parameter as optional using the 3.10 `|` syntax and it fails with a TypeError on being initialized.

### Minimal Reproducible Code

```python
from __future__ import annotations

import discord
from discord.ext import commands

import config

bot = commands.Bot(command_prefix=commands.when_mentioned, intents=discord.Intents.default())


@bot.command()
async def echo(ctx: commands.Context, *, param: commands.Range[int, 1, 1000] | None) -> None:
    await ctx.send(f"{param or 'No param given'}")

bot.run(config.token)
```


### Expected Results

The annotation should get evaluated normally.

### Actual Results

```pytb
Traceback (most recent call last):
  File "/home/***/_testing/range.py", line 12, in <module>
    async def echo(ctx: commands.Context, *, param: commands.Range[int, 1, 1000] | None) -> None:
  File "/home/***/.cache/pypoetry/virtualenvs/testing-a1XER55G-py3.10/lib/python3.10/site-packages/discord/ext/commands/core.py", line 1512, in decorator
    result = command(name=name, cls=cls, *args, **kwargs)(func)
  File "/home/***/.cache/pypoetry/virtualenvs/testing-a1XER55G-py3.10/lib/python3.10/site-packages/discord/ext/commands/core.py", line 1785, in decorator
    return cls(func, name=name, **attrs)
  File "/home/***/.cache/pypoetry/virtualenvs/testing-a1XER55G-py3.10/lib/python3.10/site-packages/discord/ext/commands/core.py", line 400, in __init__
    self.callback = func
  File "/home/***/.cache/pypoetry/virtualenvs/testing-a1XER55G-py3.10/lib/python3.10/site-packages/discord/ext/commands/core.py", line 507, in callback
    self.params: Dict[str, Parameter] = get_signature_parameters(function, globalns)
  File "/home/***/.cache/pypoetry/virtualenvs/testing-a1XER55G-py3.10/lib/python3.10/site-packages/discord/ext/commands/core.py", line 161, in get_signature_parameters
    annotation = eval_annotation(annotation, globalns, globalns, cache)
  File "/home/***/.cache/pypoetry/virtualenvs/testing-a1XER55G-py3.10/lib/python3.10/site-packages/discord/utils.py", line 1074, in evaluate_annotation
    evaluated = evaluate_annotation(eval(tp, globals, locals), globals, locals, cache)
  File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'Range' and 'NoneType'
```

### Intents

Not applicable, but discord.Intents.default()

### System Information

- Python v3.10.4-final
- discord.py v2.1.0-alpha
    - discord.py metadata: v2.1.0a4584+g771476a8
- aiohttp v3.8.1
- system info: Linux 5.15.0-47-generic #51-Ubuntu SMP Thu Aug 11 07:51:15 UTC 2022

### Checklist

- [X] I have searched the open issues for duplicates.
- [X] I have shown the entire traceback, if possible.
- [X] I have removed my token from display, if visible.

### Additional Context

_No response_


Discussion:

Resolving patch:
diff --git a/discord/ext/commands/converter.py b/discord/ext/commands/converter.py
--- a/discord/ext/commands/converter.py
+++ b/discord/ext/commands/converter.py
@@ -1109,6 +1109,9 @@ def __call__(self) -> None:
             # Trick to allow it inside typing.Union
             pass
 
+        def __or__(self, rhs) -> Any:
+            return Union[self, rhs]
+
         def __class_getitem__(cls, obj) -> Range:
             if not isinstance(obj, tuple):
                 raise TypeError(f'expected tuple for arguments, received {obj.__class__!r} instead')


Test patch: