Skip to content

Commit 77540dc

Browse files
committed
Various changes
1 parent 2a92f5c commit 77540dc

File tree

5 files changed

+48
-8
lines changed

5 files changed

+48
-8
lines changed

mypy/expandtype.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
flatten_nested_unions,
3939
get_proper_type,
4040
has_param_specs,
41-
has_type_vars,
41+
has_type_var_like_default,
4242
split_with_prefix_and_suffix,
4343
)
4444
from mypy.typevartuples import split_with_instance
@@ -231,11 +231,13 @@ def visit_type_var(self, t: TypeVarType) -> Type:
231231
t = t.copy_modified(upper_bound=t.upper_bound.accept(self))
232232
repl = self.variables.get(t.id, t)
233233

234-
if has_type_vars(repl) and not isinstance(repl, Instance):
235-
if repl in self.recursive_guard: # or isinstance(repl, CallableType):
234+
if has_type_var_like_default(repl):
235+
if repl in self.recursive_guard:
236236
return repl
237237
self.recursive_guard.add(repl)
238238
repl = repl.accept(self)
239+
if isinstance(repl, TypeVarType):
240+
repl.default = repl.default.accept(self)
239241

240242
if isinstance(repl, Instance):
241243
# TODO: do we really need to do this?

mypy/nodes.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2853,6 +2853,7 @@ class is generic then it will be a type constructor of higher kind.
28532853
"fallback_to_any",
28542854
"meta_fallback_to_any",
28552855
"type_vars",
2856+
"has_type_var_default",
28562857
"has_param_spec_type",
28572858
"bases",
28582859
"_promote",
@@ -2957,6 +2958,9 @@ class is generic then it will be a type constructor of higher kind.
29572958
# Generic type variable names (full names)
29582959
type_vars: list[str]
29592960

2961+
# Whether this class has a TypeVar with a default value
2962+
has_type_var_default: bool
2963+
29602964
# Whether this class has a ParamSpec type variable
29612965
has_param_spec_type: bool
29622966

@@ -3044,6 +3048,7 @@ def __init__(self, names: SymbolTable, defn: ClassDef, module_name: str) -> None
30443048
self.defn = defn
30453049
self.module_name = module_name
30463050
self.type_vars = []
3051+
self.has_type_var_default = False
30473052
self.has_param_spec_type = False
30483053
self.has_type_var_tuple_type = False
30493054
self.bases = []
@@ -3085,6 +3090,8 @@ def add_type_vars(self) -> None:
30853090
self.has_type_var_tuple_type = False
30863091
if self.defn.type_vars:
30873092
for i, vd in enumerate(self.defn.type_vars):
3093+
if vd.has_default():
3094+
self.has_type_var_default = True
30883095
if isinstance(vd, mypy.types.ParamSpecType):
30893096
self.has_param_spec_type = True
30903097
if isinstance(vd, mypy.types.TypeVarTupleType):
@@ -3280,6 +3287,7 @@ def serialize(self) -> JsonDict:
32803287
"defn": self.defn.serialize(),
32813288
"abstract_attributes": self.abstract_attributes,
32823289
"type_vars": self.type_vars,
3290+
"has_type_var_default": self.has_type_var_default,
32833291
"has_param_spec_type": self.has_param_spec_type,
32843292
"bases": [b.serialize() for b in self.bases],
32853293
"mro": [c.fullname for c in self.mro],
@@ -3318,6 +3326,7 @@ def deserialize(cls, data: JsonDict) -> TypeInfo:
33183326
# TODO: Is there a reason to reconstruct ti.subtypes?
33193327
ti.abstract_attributes = [(attr[0], attr[1]) for attr in data["abstract_attributes"]]
33203328
ti.type_vars = data["type_vars"]
3329+
ti.has_type_var_default = data["has_type_var_default"]
33213330
ti.has_param_spec_type = data["has_param_spec_type"]
33223331
ti.bases = [mypy.types.Instance.deserialize(b) for b in data["bases"]]
33233332
_promote = []

mypy/semanal.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4154,7 +4154,7 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> bool:
41544154
type_var.line = call.line
41554155
call.analyzed = type_var
41564156
updated = True
4157-
# self.tvar_scope.bind_new(name, type_var)
4157+
# self.tvar_scope.bind_new(name, type_var) # TODO!
41584158
else:
41594159
assert isinstance(call.analyzed, TypeVarExpr)
41604160
updated = (
@@ -4422,7 +4422,7 @@ def process_paramspec_declaration(self, s: AssignmentStmt) -> bool:
44224422
paramspec_var.line = call.line
44234423
call.analyzed = paramspec_var
44244424
updated = True
4425-
self.tvar_scope.bind_new(name, paramspec_var)
4425+
# self.tvar_scope.bind_new(name, paramspec_var) # TODO!
44264426
else:
44274427
assert isinstance(call.analyzed, ParamSpecExpr)
44284428
updated = default != call.analyzed.default
@@ -4491,6 +4491,7 @@ def process_typevartuple_declaration(self, s: AssignmentStmt) -> bool:
44914491
typevartuple_var.line = call.line
44924492
call.analyzed = typevartuple_var
44934493
updated = True
4494+
# self.tvar_scope.bind_new(name, typevartuple_var) # TODO!
44944495
else:
44954496
assert isinstance(call.analyzed, TypeVarTupleExpr)
44964497
updated = default != call.analyzed.default

mypy/typeanal.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,10 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool)
430430
isinstance(res, ProperType)
431431
and isinstance(res, Instance)
432432
and not (self.defining_alias and self.nesting_level == 0)
433-
and not validate_instance(res, self.fail, t.empty_tuple_index)
433+
and (
434+
res.type.has_type_var_default
435+
or not validate_instance(res, self.fail, t.empty_tuple_index)
436+
)
434437
):
435438
fix_instance(
436439
res,
@@ -736,8 +739,9 @@ def analyze_type_with_type_info(
736739

737740
# Check type argument count.
738741
instance.args = tuple(flatten_nested_tuples(instance.args))
739-
if not (self.defining_alias and self.nesting_level == 0) and not validate_instance(
740-
instance, self.fail, empty_tuple_index
742+
if not (self.defining_alias and self.nesting_level == 0) and (
743+
not validate_instance(instance, self.fail, empty_tuple_index)
744+
or info.has_type_var_default
741745
):
742746
fix_instance(
743747
instance,

mypy/types.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3496,6 +3496,30 @@ def has_type_vars(typ: Type) -> bool:
34963496
return typ.accept(HasTypeVars())
34973497

34983498

3499+
class HasTypeVarLikeDefault(BoolTypeQuery):
3500+
def __init__(self) -> None:
3501+
super().__init__(ANY_STRATEGY)
3502+
self.skip_alias_target = True
3503+
3504+
def visit_type_var(self, t: TypeVarType) -> bool:
3505+
return t.has_default()
3506+
3507+
def visit_type_var_tuple(self, t: TypeVarTupleType) -> bool:
3508+
return t.has_default()
3509+
3510+
def visit_param_spec(self, t: ParamSpecType) -> bool:
3511+
return t.has_default()
3512+
3513+
3514+
# Use singleton since this is hot (note: call reset() before using)
3515+
_has_type_var_like_default: Final = HasTypeVarLikeDefault()
3516+
3517+
3518+
def has_type_var_like_default(typ: Type) -> bool:
3519+
_has_type_var_like_default.reset()
3520+
return typ.accept(_has_type_var_like_default)
3521+
3522+
34993523
class HasParamSpecs(BoolTypeQuery):
35003524
def __init__(self) -> None:
35013525
super().__init__(ANY_STRATEGY)

0 commit comments

Comments
 (0)