Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -8529,6 +8529,9 @@ def lookup_fully_qualified_or_none(self, fullname: str, /) -> SymbolTableNode |
except KeyError:
return None

def record_fixed_type(self, fixed: TypeInfo | TypeAlias) -> None:
pass

def fail(
self,
msg: str,
Expand Down
22 changes: 11 additions & 11 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4915,10 +4915,11 @@ def visit_type_application(self, tapp: TypeApplication) -> Type:
if tapp.expr.node.python_3_12_type_alias:
return self.type_alias_type_type()
# Subscription of a (generic) alias in runtime context, expand the alias.
item = instantiate_type_alias(
item, _ = instantiate_type_alias(
tapp.expr.node,
tapp.types,
self.chk.fail,
self.chk.note,
tapp.expr.node.no_args,
tapp,
self.chk.options,
Expand Down Expand Up @@ -4983,17 +4984,16 @@ class LongName(Generic[T]): ...
# A = List[Tuple[T, T]]
# x = A() <- same as List[Tuple[Any, Any]], see PEP 484.
disallow_any = self.chk.options.disallow_any_generics and self.is_callee
item = get_proper_type(
set_any_tvars(
alias,
[],
ctx.line,
ctx.column,
self.chk.options,
disallow_any=disallow_any,
fail=self.msg.fail,
)
item, _ = set_any_tvars(
alias,
[],
ctx.line,
ctx.column,
self.chk.options,
disallow_any=disallow_any,
fail=self.msg.fail,
)
item = get_proper_type(item)
if isinstance(item, Instance):
# Normally we get a callable type (or overloaded) with .is_type_obj() true
# representing the class's constructor
Expand Down
1 change: 1 addition & 0 deletions mypy/message_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ def with_additional_msg(self, info: str) -> ErrorMessage:
IMPLICIT_GENERIC_ANY_BUILTIN: Final = (
'Implicit generic "Any". Use "{}" and specify generic parameters'
)
NO_CYCLIC_DEFAULT: Final = "Cyclic type variable defaults are not supported"
INVALID_UNPACK: Final = "{} cannot be unpacked (must be tuple or TypeVarTuple)"
INVALID_UNPACK_POSITION: Final = "Unpack is only valid in a variadic position"
INVALID_PARAM_SPEC_LOCATION: Final = "Invalid location for ParamSpec {}"
Expand Down
29 changes: 28 additions & 1 deletion mypy/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3145,7 +3145,15 @@ class TypeVarLikeExpr(SymbolNode, Expression):
Note that they are constructed by the semantic analyzer.
"""

__slots__ = ("_name", "_fullname", "upper_bound", "default", "variance", "is_new_style")
__slots__ = (
"_name",
"_fullname",
"upper_bound",
"default",
"variance",
"is_new_style",
"default_depends",
)

_name: str
_fullname: str
Expand All @@ -3160,6 +3168,9 @@ class TypeVarLikeExpr(SymbolNode, Expression):
# TypeVar(..., contravariant=True) defines a contravariant type
# variable.
variance: int
# Record instances and type aliases that appear bare/implicit in the default value
# of this type variable. This is needed to detect recursive type variable defaults.
default_depends: set[TypeInfo | TypeAlias] | None

def __init__(
self,
Expand All @@ -3178,6 +3189,7 @@ def __init__(
self.default = default
self.variance = variance
self.is_new_style = is_new_style
self.default_depends = None

@property
def name(self) -> str:
Expand Down Expand Up @@ -3655,6 +3667,7 @@ class is generic then it will be a type constructor of higher kind.
"is_type_check_only",
"deprecated",
"type_object_type",
"default_depends",
)

_fullname: str # Fully qualified name
Expand Down Expand Up @@ -3816,6 +3829,16 @@ class is generic then it will be a type constructor of higher kind.
# appears in runtime context.
type_object_type: mypy.types.FunctionLike | None

# Type variables whose defaults depend on defaults of type variables in other classes
# and type aliases. We keep track of this to safely handle situations like this one:
# class C[T = D]: ...
# class D[S = C]: ...
# x: C
# Since we apply fix_instance() eagerly, inferring a precise type is quite tricky.
# Therefore, we infer the type of `x` as `C[D[Any]]` to avoid infinite recursion.
# Keys are type variable full names.
default_depends: dict[str, set[TypeAlias | TypeInfo]]

FLAGS: Final = [
"is_abstract",
"is_enum",
Expand Down Expand Up @@ -3877,6 +3900,7 @@ def __init__(self, names: SymbolTable, defn: ClassDef, module_name: str) -> None
self.is_type_check_only = False
self.deprecated = None
self.type_object_type = None
self.default_depends = {}

def add_type_vars(self) -> None:
self.has_type_var_tuple_type = False
Expand Down Expand Up @@ -4542,6 +4566,7 @@ def f(x: B[T]) -> T: ... # without T, Any would be used here
"eager",
"tvar_tuple_index",
"python_3_12_type_alias",
"default_depends",
)

__match_args__ = ("name", "target", "alias_tvars", "no_args")
Expand Down Expand Up @@ -4574,6 +4599,8 @@ def __init__(
self.eager = eager
self.python_3_12_type_alias = python_3_12_type_alias
self.tvar_tuple_index = None
# This plays the same role as TypeInfo.default_depends attribute.
self.default_depends: dict[str, set[TypeAlias | TypeInfo]] = {}
for i, t in enumerate(alias_tvars):
if isinstance(t, mypy.types.TypeVarTupleType):
self.tvar_tuple_index = i
Expand Down
Loading
Loading