[3.10] bpo-46032: Check types in singledispatch's register() at declaration time (GH-30050) (GH-30254)

The registry() method of functools.singledispatch() functions checks now
the first argument or the first parameter annotation and raises a TypeError if it is
not supported. Previously unsupported "types" were ignored (e.g. typing.List[int])
or caused an error at calling time (e.g. list[int]).

(cherry picked from commit 078abb676cf759b1e960f78390b6e80f256f0255)
diff --git a/Lib/functools.py b/Lib/functools.py
index 77ec852..305ceb4 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -740,6 +740,7 @@ def _compose_mro(cls, types):
     # Remove entries which are already present in the __mro__ or unrelated.
     def is_related(typ):
         return (typ not in bases and hasattr(typ, '__mro__')
+                                 and not isinstance(typ, GenericAlias)
                                  and issubclass(cls, typ))
     types = [n for n in types if is_related(n)]
     # Remove entries which are strict bases of other entries (they will end up
@@ -837,6 +838,9 @@ def dispatch(cls):
             dispatch_cache[cls] = impl
         return impl
 
+    def _is_valid_dispatch_type(cls):
+        return isinstance(cls, type) and not isinstance(cls, GenericAlias)
+
     def register(cls, func=None):
         """generic_func.register(cls, func) -> func
 
@@ -844,9 +848,15 @@ def register(cls, func=None):
 
         """
         nonlocal cache_token
-        if func is None:
-            if isinstance(cls, type):
+        if _is_valid_dispatch_type(cls):
+            if func is None:
                 return lambda f: register(cls, f)
+        else:
+            if func is not None:
+                raise TypeError(
+                    f"Invalid first argument to `register()`. "
+                    f"{cls!r} is not a class."
+                )
             ann = getattr(cls, '__annotations__', {})
             if not ann:
                 raise TypeError(
@@ -859,11 +869,12 @@ def register(cls, func=None):
             # only import typing if annotation parsing is necessary
             from typing import get_type_hints
             argname, cls = next(iter(get_type_hints(func).items()))
-            if not isinstance(cls, type):
+            if not _is_valid_dispatch_type(cls):
                 raise TypeError(
                     f"Invalid annotation for {argname!r}. "
                     f"{cls!r} is not a class."
                 )
+
         registry[cls] = func
         if cache_token is None and hasattr(cls, '__abstractmethods__'):
             cache_token = get_cache_token()