prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Error validating return types when using a Generic in Union
  There seems to be an issue with types.
  Generics worked fine and dandy until I've tried to use them in a Union.
  
  ```python
  @strawberry.type
  class FaultyType:
      code_sent: bool
      result: Union[Pet, ErrorNode[Codes]]
  ```
  Here returning an ErrorNode in "result" field fails type check.
  Fails with strawberry.exceptions.UnallowedReturnTypeForUnion: The type "<class 'strawberry_sample.ErrorNode'>" of the field "result" is not in the list of the types of the union: "['CodesErrorNode', 'Pet']"
  
  Returning the same generic without unions in type declaration works fine.
  
  Full sample:
  https://gist.github.com/MeRuslan/5bd179f28fc5ae05e815429ee02ebdf6
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `strawberry/types/types.py`
  Content:
  ```
  1 from __future__ import annotations
  2 
  3 import dataclasses
  4 from typing import (
  5     TYPE_CHECKING,
  6     List,
  7     Mapping,
  8     Optional,
  9     Sequence,
  10     Type,
  11     TypeVar,
  12     Union,
  13 )
  14 
  15 from strawberry.type import StrawberryType, StrawberryTypeVar
  16 from strawberry.utils.typing import is_generic as is_type_generic
  17 
  18 
  19 if TYPE_CHECKING:
  20     from strawberry.field import StrawberryField
  21     from strawberry.schema_directive import StrawberrySchemaDirective
  22 
  23 
  24 @dataclasses.dataclass(eq=False)
  25 class TypeDefinition(StrawberryType):
  26     name: str
  27     is_input: bool
  28     is_interface: bool
  29     origin: Type
  30     description: Optional[str]
  31     interfaces: List["TypeDefinition"]
  32     extend: bool
  33     directives: Optional[Sequence[StrawberrySchemaDirective]]
  34 
  35     _fields: List["StrawberryField"]
  36 
  37     concrete_of: Optional["TypeDefinition"] = None
  38     """Concrete implementations of Generic TypeDefinitions fill this in"""
  39     type_var_map: Mapping[TypeVar, Union[StrawberryType, type]] = dataclasses.field(
  40         default_factory=dict
  41     )
  42 
  43     # TODO: remove wrapped cls when we "merge" this with `StrawberryObject`
  44     def resolve_generic(self, wrapped_cls: type) -> type:
  45         from strawberry.annotation import StrawberryAnnotation
  46 
  47         passed_types = wrapped_cls.__args__  # type: ignore
  48         params = wrapped_cls.__origin__.__parameters__  # type: ignore
  49 
  50         # Make sure all passed_types are turned into StrawberryTypes
  51         resolved_types = []
  52         for passed_type in passed_types:
  53             resolved_type = StrawberryAnnotation(passed_type).resolve()
  54             resolved_types.append(resolved_type)
  55 
  56         type_var_map = dict(zip(params, resolved_types))
  57 
  58         return self.copy_with(type_var_map)
  59 
  60     # TODO: Return a StrawberryObject
  61     def copy_with(
  62         self, type_var_map: Mapping[TypeVar, Union[StrawberryType, type]]
  63     ) -> type:
  64         fields = []
  65         for field in self.fields:
  66             # TODO: Logic unnecessary with StrawberryObject
  67             field_type = field.type
  68             if hasattr(field_type, "_type_definition"):
  69                 field_type = field_type._type_definition  # type: ignore
  70 
  71             # TODO: All types should end up being StrawberryTypes
  72             #       The first check is here as a symptom of strawberry.ID being a
  73             #       Scalar, but not a StrawberryType
  74             if isinstance(field_type, StrawberryType) and field_type.is_generic:
  75                 field = field.copy_with(type_var_map)
  76 
  77             fields.append(field)
  78 
  79         new_type_definition = TypeDefinition(
  80             name=self.name,
  81             is_input=self.is_input,
  82             origin=self.origin,
  83             is_interface=self.is_interface,
  84             directives=self.directives,
  85             interfaces=self.interfaces,
  86             description=self.description,
  87             extend=self.extend,
  88             _fields=fields,
  89             concrete_of=self,
  90             type_var_map=type_var_map,
  91         )
  92 
  93         new_type = type(
  94             new_type_definition.name,
  95             (self.origin,),
  96             {"_type_definition": new_type_definition},
  97         )
  98 
  99         new_type_definition.origin = new_type
  100 
  101         return new_type
  102 
  103     def get_field(self, python_name: str) -> Optional["StrawberryField"]:
  104         return next(
  105             (field for field in self.fields if field.python_name == python_name), None
  106         )
  107 
  108     @property
  109     def fields(self) -> List["StrawberryField"]:
  110         # TODO: rename _fields to fields and remove this property
  111         return self._fields
  112 
  113     @property
  114     def is_generic(self) -> bool:
  115         return is_type_generic(self.origin)
  116 
  117     @property
  118     def type_params(self) -> List[TypeVar]:
  119         type_params: List[TypeVar] = []
  120         for field in self.fields:
  121             type_params.extend(field.type_params)
  122 
  123         return type_params
  124 
  125     def is_implemented_by(self, root: Union[type, dict]) -> bool:
  126         # TODO: Accept StrawberryObject instead
  127         # TODO: Support dicts
  128         if isinstance(root, dict):
  129             raise NotImplementedError()
  130 
  131         type_definition = root._type_definition  # type: ignore
  132 
  133         if type_definition is self:
  134             # No generics involved. Exact type match
  135             return True
  136 
  137         if type_definition is not self.concrete_of:
  138             # Either completely different type, or concrete type of a different generic
  139             return False
  140 
  141         # Check the mapping of all fields' TypeVars
  142         for generic_field in type_definition.fields:
  143             generic_field_type = generic_field.type
  144             if not isinstance(generic_field_type, StrawberryTypeVar):
  145                 continue
  146 
  147             # For each TypeVar found, get the expected type from the copy's type map
  148             expected_concrete_type = self.type_var_map.get(generic_field_type.type_var)
  149             if expected_concrete_type is None:
  150                 # TODO: Should this return False?
  151                 continue
  152 
  153             # Check if the expected type matches the type found on the type_map
  154             real_concrete_type = type(getattr(root, generic_field.name))
  155             if real_concrete_type is not expected_concrete_type:
  156                 return False
  157 
  158         # All field mappings succeeded. This is a match
  159         return True
  160
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/strawberry/types/types.py b/strawberry/types/types.py
  --- a/strawberry/types/types.py
  +++ b/strawberry/types/types.py
  @@ -152,6 +152,13 @@
   
               # Check if the expected type matches the type found on the type_map
               real_concrete_type = type(getattr(root, generic_field.name))
  +
  +            # TODO: uniform type var map, at the moment we map object types
  +            # to their class (not to TypeDefinition) while we map enum to
  +            # the EnumDefinition class. This is why we do this check here:
  +            if hasattr(real_concrete_type, "_enum_definition"):
  +                real_concrete_type = real_concrete_type._enum_definition
  +
               if real_concrete_type is not expected_concrete_type:
                   return False
  
verification_info: {"golden_diff": "diff --git a/strawberry/types/types.py b/strawberry/types/types.py\n--- a/strawberry/types/types.py\n+++ b/strawberry/types/types.py\n@@ -152,6 +152,13 @@\n \n             # Check if the expected type matches the type found on the type_map\n             real_concrete_type = type(getattr(root, generic_field.name))\n+\n+            # TODO: uniform type var map, at the moment we map object types\n+            # to their class (not to TypeDefinition) while we map enum to\n+            # the EnumDefinition class. This is why we do this check here:\n+            if hasattr(real_concrete_type, \"_enum_definition\"):\n+                real_concrete_type = real_concrete_type._enum_definition\n+\n             if real_concrete_type is not expected_concrete_type:\n                 return False\n", "issue": "Error validating return types when using a Generic in Union\nThere seems to be an issue with types.\r\nGenerics worked fine and dandy until I've tried to use them in a Union.\r\n\r\n```python\r\n@strawberry.type\r\nclass FaultyType:\r\n    code_sent: bool\r\n    result: Union[Pet, ErrorNode[Codes]]\r\n```\r\nHere returning an ErrorNode in \"result\" field fails type check.\r\nFails with strawberry.exceptions.UnallowedReturnTypeForUnion: The type \"<class 'strawberry_sample.ErrorNode'>\" of the field \"result\" is not in the list of the types of the union: \"['CodesErrorNode', 'Pet']\"\r\n\r\nReturning the same generic without unions in type declaration works fine.\r\n\r\nFull sample:\r\nhttps://gist.github.com/MeRuslan/5bd179f28fc5ae05e815429ee02ebdf6\n", "before_files": [{"content": "from __future__ import annotations\n\nimport dataclasses\nfrom typing import (\n    TYPE_CHECKING,\n    List,\n    Mapping,\n    Optional,\n    Sequence,\n    Type,\n    TypeVar,\n    Union,\n)\n\nfrom strawberry.type import StrawberryType, StrawberryTypeVar\nfrom strawberry.utils.typing import is_generic as is_type_generic\n\n\nif TYPE_CHECKING:\n    from strawberry.field import StrawberryField\n    from strawberry.schema_directive import StrawberrySchemaDirective\n\n\n@dataclasses.dataclass(eq=False)\nclass TypeDefinition(StrawberryType):\n    name: str\n    is_input: bool\n    is_interface: bool\n    origin: Type\n    description: Optional[str]\n    interfaces: List[\"TypeDefinition\"]\n    extend: bool\n    directives: Optional[Sequence[StrawberrySchemaDirective]]\n\n    _fields: List[\"StrawberryField\"]\n\n    concrete_of: Optional[\"TypeDefinition\"] = None\n    \"\"\"Concrete implementations of Generic TypeDefinitions fill this in\"\"\"\n    type_var_map: Mapping[TypeVar, Union[StrawberryType, type]] = dataclasses.field(\n        default_factory=dict\n    )\n\n    # TODO: remove wrapped cls when we \"merge\" this with `StrawberryObject`\n    def resolve_generic(self, wrapped_cls: type) -> type:\n        from strawberry.annotation import StrawberryAnnotation\n\n        passed_types = wrapped_cls.__args__  # type: ignore\n        params = wrapped_cls.__origin__.__parameters__  # type: ignore\n\n        # Make sure all passed_types are turned into StrawberryTypes\n        resolved_types = []\n        for passed_type in passed_types:\n            resolved_type = StrawberryAnnotation(passed_type).resolve()\n            resolved_types.append(resolved_type)\n\n        type_var_map = dict(zip(params, resolved_types))\n\n        return self.copy_with(type_var_map)\n\n    # TODO: Return a StrawberryObject\n    def copy_with(\n        self, type_var_map: Mapping[TypeVar, Union[StrawberryType, type]]\n    ) -> type:\n        fields = []\n        for field in self.fields:\n            # TODO: Logic unnecessary with StrawberryObject\n            field_type = field.type\n            if hasattr(field_type, \"_type_definition\"):\n                field_type = field_type._type_definition  # type: ignore\n\n            # TODO: All types should end up being StrawberryTypes\n            #       The first check is here as a symptom of strawberry.ID being a\n            #       Scalar, but not a StrawberryType\n            if isinstance(field_type, StrawberryType) and field_type.is_generic:\n                field = field.copy_with(type_var_map)\n\n            fields.append(field)\n\n        new_type_definition = TypeDefinition(\n            name=self.name,\n            is_input=self.is_input,\n            origin=self.origin,\n            is_interface=self.is_interface,\n            directives=self.directives,\n            interfaces=self.interfaces,\n            description=self.description,\n            extend=self.extend,\n            _fields=fields,\n            concrete_of=self,\n            type_var_map=type_var_map,\n        )\n\n        new_type = type(\n            new_type_definition.name,\n            (self.origin,),\n            {\"_type_definition\": new_type_definition},\n        )\n\n        new_type_definition.origin = new_type\n\n        return new_type\n\n    def get_field(self, python_name: str) -> Optional[\"StrawberryField\"]:\n        return next(\n            (field for field in self.fields if field.python_name == python_name), None\n        )\n\n    @property\n    def fields(self) -> List[\"StrawberryField\"]:\n        # TODO: rename _fields to fields and remove this property\n        return self._fields\n\n    @property\n    def is_generic(self) -> bool:\n        return is_type_generic(self.origin)\n\n    @property\n    def type_params(self) -> List[TypeVar]:\n        type_params: List[TypeVar] = []\n        for field in self.fields:\n            type_params.extend(field.type_params)\n\n        return type_params\n\n    def is_implemented_by(self, root: Union[type, dict]) -> bool:\n        # TODO: Accept StrawberryObject instead\n        # TODO: Support dicts\n        if isinstance(root, dict):\n            raise NotImplementedError()\n\n        type_definition = root._type_definition  # type: ignore\n\n        if type_definition is self:\n            # No generics involved. Exact type match\n            return True\n\n        if type_definition is not self.concrete_of:\n            # Either completely different type, or concrete type of a different generic\n            return False\n\n        # Check the mapping of all fields' TypeVars\n        for generic_field in type_definition.fields:\n            generic_field_type = generic_field.type\n            if not isinstance(generic_field_type, StrawberryTypeVar):\n                continue\n\n            # For each TypeVar found, get the expected type from the copy's type map\n            expected_concrete_type = self.type_var_map.get(generic_field_type.type_var)\n            if expected_concrete_type is None:\n                # TODO: Should this return False?\n                continue\n\n            # Check if the expected type matches the type found on the type_map\n            real_concrete_type = type(getattr(root, generic_field.name))\n            if real_concrete_type is not expected_concrete_type:\n                return False\n\n        # All field mappings succeeded. This is a match\n        return True\n", "path": "strawberry/types/types.py"}], "after_files": [{"content": "from __future__ import annotations\n\nimport dataclasses\nfrom typing import (\n    TYPE_CHECKING,\n    List,\n    Mapping,\n    Optional,\n    Sequence,\n    Type,\n    TypeVar,\n    Union,\n)\n\nfrom strawberry.type import StrawberryType, StrawberryTypeVar\nfrom strawberry.utils.typing import is_generic as is_type_generic\n\n\nif TYPE_CHECKING:\n    from strawberry.field import StrawberryField\n    from strawberry.schema_directive import StrawberrySchemaDirective\n\n\n@dataclasses.dataclass(eq=False)\nclass TypeDefinition(StrawberryType):\n    name: str\n    is_input: bool\n    is_interface: bool\n    origin: Type\n    description: Optional[str]\n    interfaces: List[\"TypeDefinition\"]\n    extend: bool\n    directives: Optional[Sequence[StrawberrySchemaDirective]]\n\n    _fields: List[\"StrawberryField\"]\n\n    concrete_of: Optional[\"TypeDefinition\"] = None\n    \"\"\"Concrete implementations of Generic TypeDefinitions fill this in\"\"\"\n    type_var_map: Mapping[TypeVar, Union[StrawberryType, type]] = dataclasses.field(\n        default_factory=dict\n    )\n\n    # TODO: remove wrapped cls when we \"merge\" this with `StrawberryObject`\n    def resolve_generic(self, wrapped_cls: type) -> type:\n        from strawberry.annotation import StrawberryAnnotation\n\n        passed_types = wrapped_cls.__args__  # type: ignore\n        params = wrapped_cls.__origin__.__parameters__  # type: ignore\n\n        # Make sure all passed_types are turned into StrawberryTypes\n        resolved_types = []\n        for passed_type in passed_types:\n            resolved_type = StrawberryAnnotation(passed_type).resolve()\n            resolved_types.append(resolved_type)\n\n        type_var_map = dict(zip(params, resolved_types))\n\n        return self.copy_with(type_var_map)\n\n    # TODO: Return a StrawberryObject\n    def copy_with(\n        self, type_var_map: Mapping[TypeVar, Union[StrawberryType, type]]\n    ) -> type:\n        fields = []\n        for field in self.fields:\n            # TODO: Logic unnecessary with StrawberryObject\n            field_type = field.type\n            if hasattr(field_type, \"_type_definition\"):\n                field_type = field_type._type_definition  # type: ignore\n\n            # TODO: All types should end up being StrawberryTypes\n            #       The first check is here as a symptom of strawberry.ID being a\n            #       Scalar, but not a StrawberryType\n            if isinstance(field_type, StrawberryType) and field_type.is_generic:\n                field = field.copy_with(type_var_map)\n\n            fields.append(field)\n\n        new_type_definition = TypeDefinition(\n            name=self.name,\n            is_input=self.is_input,\n            origin=self.origin,\n            is_interface=self.is_interface,\n            directives=self.directives,\n            interfaces=self.interfaces,\n            description=self.description,\n            extend=self.extend,\n            _fields=fields,\n            concrete_of=self,\n            type_var_map=type_var_map,\n        )\n\n        new_type = type(\n            new_type_definition.name,\n            (self.origin,),\n            {\"_type_definition\": new_type_definition},\n        )\n\n        new_type_definition.origin = new_type\n\n        return new_type\n\n    def get_field(self, python_name: str) -> Optional[\"StrawberryField\"]:\n        return next(\n            (field for field in self.fields if field.python_name == python_name), None\n        )\n\n    @property\n    def fields(self) -> List[\"StrawberryField\"]:\n        # TODO: rename _fields to fields and remove this property\n        return self._fields\n\n    @property\n    def is_generic(self) -> bool:\n        return is_type_generic(self.origin)\n\n    @property\n    def type_params(self) -> List[TypeVar]:\n        type_params: List[TypeVar] = []\n        for field in self.fields:\n            type_params.extend(field.type_params)\n\n        return type_params\n\n    def is_implemented_by(self, root: Union[type, dict]) -> bool:\n        # TODO: Accept StrawberryObject instead\n        # TODO: Support dicts\n        if isinstance(root, dict):\n            raise NotImplementedError()\n\n        type_definition = root._type_definition  # type: ignore\n\n        if type_definition is self:\n            # No generics involved. Exact type match\n            return True\n\n        if type_definition is not self.concrete_of:\n            # Either completely different type, or concrete type of a different generic\n            return False\n\n        # Check the mapping of all fields' TypeVars\n        for generic_field in type_definition.fields:\n            generic_field_type = generic_field.type\n            if not isinstance(generic_field_type, StrawberryTypeVar):\n                continue\n\n            # For each TypeVar found, get the expected type from the copy's type map\n            expected_concrete_type = self.type_var_map.get(generic_field_type.type_var)\n            if expected_concrete_type is None:\n                # TODO: Should this return False?\n                continue\n\n            # Check if the expected type matches the type found on the type_map\n            real_concrete_type = type(getattr(root, generic_field.name))\n\n            # TODO: uniform type var map, at the moment we map object types\n            # to their class (not to TypeDefinition) while we map enum to\n            # the EnumDefinition class. This is why we do this check here:\n            if hasattr(real_concrete_type, \"_enum_definition\"):\n                real_concrete_type = real_concrete_type._enum_definition\n\n            if real_concrete_type is not expected_concrete_type:\n                return False\n\n        # All field mappings succeeded. This is a match\n        return True\n", "path": "strawberry/types/types.py"}]}