Repository: pydantic/pydantic

Issue:
Field of Type[Union[...]] fails in V2
### Initial Checks

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

### Description

Pydantic V2 no longer supports annotating a field using `Type` before `Union`. A model with the following field:
```python
Type[Union[str, bytes]]
```

Gives the following traceback:
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ubuntu/mambaforge/envs/***/lib/python3.11/site-packages/pydantic/_internal/_model_construction.py", line 174, in __new__
    complete_model_class(
  File "/home/ubuntu/mambaforge/envs/***/lib/python3.11/site-packages/pydantic/_internal/_model_construction.py", line 449, in complete_model_class
    cls.__pydantic_validator__ = SchemaValidator(simplified_core_schema, core_config)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.SchemaError: Error building "model" validator:
  SchemaError: Error building "model-fields" validator:
  SchemaError: Field "s":
  SchemaError: Error building "is-subclass" validator:
  TypeError: '_UnionGenericAlias' object cannot be converted to 'PyType'
```

### Example Code

```Python
from typing import Type, Union

import pydantic

class MyModel(pydantic.BaseModel):
    s: Type[Union[str, bytes]]
```


### Python, Pydantic & OS Version

```Text
pydantic version: 2.0.3
pydantic-core version: 2.3.0 release build profile
install path: /home/ubuntu/mambaforge/envs/***/lib/python3.11/site-packages/pydantic
python version: 3.11.4 | packaged by conda-forge | (main, Jun 10 2023, 18:08:17) [GCC 12.2.0]
platform: Linux-5.15.0-76-generic-x86_64-with-glibc2.35
optional deps. installed: ['typing-extensions']
```


Selected Assignee: @dmontagu


Discussion:
For anyone experiencing the bug, a workaround is defining the field using:
```python
Union[Type[str], Type[bytes]]
```

I still created the issue because I guess this is an unexpected breaking change from V1
It's a bug. Thanks for reporting it @giacomorebecchi 🙏 

We need to solve it on `pydantic-core`.

Resolving patch:
diff --git a/pydantic/_internal/_generate_schema.py b/pydantic/_internal/_generate_schema.py
--- a/pydantic/_internal/_generate_schema.py
+++ b/pydantic/_internal/_generate_schema.py
@@ -1094,6 +1094,9 @@ def _subclass_schema(self, type_: Any) -> core_schema.CoreSchema:
                 )
             else:
                 return self._type_schema()
+        elif _typing_extra.origin_is_union(get_origin(type_param)):
+            args = self._get_args_resolving_forward_refs(type_param, required=True)
+            return core_schema.union_schema([self.generate_schema(typing.Type[args]) for args in args])
         else:
             return core_schema.is_subclass_schema(type_param)
 


Test patch:
diff --git a/tests/test_edge_cases.py b/tests/test_edge_cases.py
--- a/tests/test_edge_cases.py
+++ b/tests/test_edge_cases.py
@@ -2580,3 +2580,13 @@ class Model(BaseModel):
     m = Model(value=data, value_types_reversed=data)
     assert m.model_dump() == {'value': data, 'value_types_reversed': data_reversed}
     assert m.model_dump_json() == f'{{"value":{json_value},"value_types_reversed":{json_value_reversed}}}'
+
+
+def test_type_union():
+    class Model(BaseModel):
+        a: Type[Union[str, bytes]]
+        b: Type[Union[Any, str]]
+
+    m = Model(a=bytes, b=int)
+    assert m.model_dump() == {'a': bytes, 'b': int}
+    assert m.a == bytes