Repository: Rapptz/discord.py
Pull request: Raise TypeError when Optional is used with Greedy converter
### Summary

This closes #2253. Having Union[..., `None`] makes no sense in Greedy, and should throw an error.

### Checklist

<!-- Put an x inside [ ] to check it, like so: [x] -->

- [x] If code changes were made then they have been tested.
    - [x] I have updated the documentation to reflect the changes.
- [x] This PR fixes an issue.
- [ ] This PR adds something new (e.g. new method or parameters).
- [x] This PR is a breaking change (e.g. methods or parameters removed/renamed)
- [ ] This PR is **not** a code change (e.g. documentation, README, ...)


Problem statement:
[Commands] Using a typing.Optional[] converter in a commands.Greedy[] one
### Summary

I tried making a command with an argument like
`cmd(ctx, arg: commands.Greedy[typing.Optional[int]])`
(actual command and types not shown, but they work on their own)
However, the bot gets stuck in an infinite loop in Command._transform_greedy_pos().

### Reproduction Steps

I had a typing.optional[] type in a command's commands.Greedy[] converter. Similar to
`cmd(ctx, arg: commands.Greedy[typing.Optional[int]])`

### Expected Results

For this example, if I had a command like
`>command str 1 2 str 3`
arg would be passed a value of
`[None, 1, 2, None, 3]`
since the strings would get converted to `None` under the typing.Optional converter

### Actual Results

The bot is stuck in an infinite loop between lines 460-476 of core.py, in Command._transform_greedy_pos() at the loop 'while not view.eof'


### Checklist

- [x] I have searched the open issues for duplicates.
- [ ] I have shown the entire traceback, if possible.
- [x] I have removed my token from display, if visible.

### System Information

```
- Python v3.6.8-final
- discord.py v1.2.3-final
- aiohttp v3.5.4
- websockets v6.0
- system info: Windows 10 10.0.17134
```

Hints from issue discussion:
This should probably just error out since it doesn't make sense.

Commit message: Raise TypeError when Optional is used with Greedy converter

Patch to review:
diff --git a/discord/ext/commands/converter.py b/discord/ext/commands/converter.py
index 3d706bf80eeb..993aed776dce 100644
--- a/discord/ext/commands/converter.py
+++ b/discord/ext/commands/converter.py
@@ -26,6 +26,7 @@
 
 import re
 import inspect
+import typing
 
 import discord
 
@@ -555,6 +556,9 @@ def __getitem__(self, params):
         if converter is str or converter is type(None) or converter is _Greedy:
             raise TypeError('Greedy[%s] is invalid.' % converter.__name__)
 
+        if getattr(converter, '__origin__', None) is typing.Union and type(None) in converter.__args__:
+            raise TypeError('Greedy[Optional] is invalid.')
+
         return self.__class__(converter=converter)
 
 Greedy = _Greedy()
diff --git a/docs/ext/commands/commands.rst b/docs/ext/commands/commands.rst
index fbf87fc27ab3..523de3e3e5e8 100644
--- a/docs/ext/commands/commands.rst
+++ b/docs/ext/commands/commands.rst
@@ -552,8 +552,8 @@ This command can be invoked any of the following ways:
     unintended parsing ambiguities in your code. One technique would be to clamp down the expected syntaxes
     allowed through custom converters or reordering the parameters to minimise clashes.
 
-    To help aid with some parsing ambiguities, :class:`str`, ``None`` and :data:`~ext.commands.Greedy` are
-    forbidden as parameters for the :data:`~ext.commands.Greedy` converter.
+    To help aid with some parsing ambiguities, :class:`str`, ``None``, :data:`typing.Optional` and
+    :data:`~ext.commands.Greedy` are forbidden as parameters for the :data:`~ext.commands.Greedy` converter.
 
 .. _ext_commands_error_handler:
 


Code review comments:
diff_hunk: @@ -555,6 +556,9 @@ def __getitem__(self, params):
         if converter is str or converter is type(None) or converter is _Greedy:
             raise TypeError('Greedy[%s] is invalid.' % converter.__name__)
 
+        if getattr(converter, '__origin__', None) is typing.Union and type(None) in converter.__args__:
+            raise TypeError('Greedy[Optional] is invalid.')
path: discord/ext/commands/converter.py
text: @user1:
```suggestion
            raise TypeError('Greedy[%r] is invalid.' % converter)
```