Visitor that substitutes type variables with values.
| 175 | |
| 176 | |
| 177 | class ExpandTypeVisitor(TrivialSyntheticTypeTranslator): |
| 178 | """Visitor that substitutes type variables with values.""" |
| 179 | |
| 180 | variables: Mapping[TypeVarId, Type] # TypeVar id -> TypeVar value |
| 181 | |
| 182 | def __init__(self, variables: Mapping[TypeVarId, Type]) -> None: |
| 183 | super().__init__() |
| 184 | self.variables = variables |
| 185 | self.recursive_tvar_guard: dict[TypeVarId, Type | None] | None = None |
| 186 | |
| 187 | def visit_unbound_type(self, t: UnboundType) -> Type: |
| 188 | return t |
| 189 | |
| 190 | def visit_any(self, t: AnyType) -> Type: |
| 191 | return t |
| 192 | |
| 193 | def visit_none_type(self, t: NoneType) -> Type: |
| 194 | return t |
| 195 | |
| 196 | def visit_uninhabited_type(self, t: UninhabitedType) -> Type: |
| 197 | return t |
| 198 | |
| 199 | def visit_deleted_type(self, t: DeletedType) -> Type: |
| 200 | return t |
| 201 | |
| 202 | def visit_erased_type(self, t: ErasedType) -> Type: |
| 203 | # This may happen during type inference if some function argument |
| 204 | # type is a generic callable, and its erased form will appear in inferred |
| 205 | # constraints, then solver may check subtyping between them, which will trigger |
| 206 | # unify_generic_callables(), this is why we can get here. Another example is |
| 207 | # when inferring type of lambda in generic context, the lambda body contains |
| 208 | # a generic method in generic class. |
| 209 | return t |
| 210 | |
| 211 | def visit_instance(self, t: Instance) -> Type: |
| 212 | if len(t.args) == 0: |
| 213 | return t |
| 214 | |
| 215 | args = self.expand_type_tuple_with_unpack(t.args) |
| 216 | |
| 217 | if isinstance(t.type, FakeInfo): |
| 218 | # The type checker expands function definitions and bodies |
| 219 | # if they depend on constrained type variables but the body |
| 220 | # might contain a tuple type comment (e.g., # type: (int, float)), |
| 221 | # in which case 't.type' is not yet available. |
| 222 | # |
| 223 | # See: https://github.com/python/mypy/issues/16649 |
| 224 | return t.copy_modified(args=args) |
| 225 | |
| 226 | if t.type.fullname == "builtins.tuple": |
| 227 | # Normalize Tuple[*Tuple[X, ...], ...] -> Tuple[X, ...] |
| 228 | arg = args[0] |
| 229 | if isinstance(arg, UnpackType): |
| 230 | unpacked = get_proper_type(arg.type) |
| 231 | if isinstance(unpacked, Instance): |
| 232 | # TODO: this and similar asserts below may be unsafe because get_proper_type() |
| 233 | # may be called during semantic analysis before all invalid types are removed. |
| 234 | assert unpacked.type.fullname == "builtins.tuple" |
no outgoing calls
no test coverage detected
searching dependent graphs…