Skip to content
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 @@ -4938,10 +4938,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 @@ -5006,17 +5007,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 @@ -4548,6 +4572,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 @@ -4580,6 +4605,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