@@ -538,6 +538,10 @@ def __init__(
538538 # [b.py]
539539 # import foo.bar
540540 self .transitive_submodule_imports : dict [str , set [str ]] = {}
541+
542+ # Instances and type aliases that were fixed using default valuers of type
543+ # variables. This can be used on-demand by type analyzer. Use record_fixed_type()
544+ # to create the set lazily.
541545 self .types_fixed : set [TypeInfo | TypeAlias ] | None = None
542546
543547 # mypyc doesn't properly handle implementing an abstractproperty
@@ -1990,8 +1994,10 @@ def analyze_class(self, defn: ClassDef) -> None:
19901994 default_depends [tv .fullname ] = tv .default_depends
19911995
19921996 if any (has_placeholder (tvd ) for tvd in tvar_defs ):
1993- # Some type variable bounds or values are not ready, we need
1994- # to re-analyze this class.
1997+ # Some type variable bounds or values are not ready, we need to
1998+ # re-analyze this class. Note we force progress to handle cases like
1999+ # class C[T = C], this matches logic in process_typevar_parameters()
2000+ # for "old style" type variables.
19952001 self .defer (force_progress = tvar_defs != defn .type_vars )
19962002
19972003 self .analyze_class_keywords (defn )
@@ -2283,7 +2289,8 @@ class Foo(Bar, Generic[T]): ...
22832289
22842290 Note that this is performed *before* semantic analysis.
22852291
2286- Returns (remaining base expressions, inferred type variables, is protocol).
2292+ Returns a tuple:
2293+ (remaining base expressions, type variables, is protocol, type variable expressions).
22872294 """
22882295 removed : list [int ] = []
22892296 declared_tvars : TypeVarLikeList = []
@@ -3993,7 +4000,8 @@ def analyze_alias(
39934000 """Check if 'rvalue' is a valid type allowed for aliasing (e.g. not a type variable).
39944001
39954002 If yes, return the corresponding type, a list of type variables for generic aliases,
3996- a set of names the alias depends on, and True if the original type has empty tuple index.
4003+ a set of names the alias depends on, whether the original type has empty tuple index,
4004+ and any type variables whose defaults depend on other classes or type aliases.
39974005 An example for the dependencies:
39984006 A = int
39994007 B = str
@@ -4179,9 +4187,6 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool:
41794187 self .mark_incomplete (lvalue .name , rvalue , becomes_typeinfo = True )
41804188 return True
41814189
4182- if any (has_placeholder (tv ) for tv in alias_tvars ):
4183- self .defer ()
4184-
41854190 self .add_type_alias_deps (depends_on )
41864191 check_for_explicit_any (res , self .options , self .is_typeshed_stub_file , self .msg , context = s )
41874192 # When this type alias gets "inlined", the Any is not explicit anymore,
@@ -4236,7 +4241,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool:
42364241 # An alias gets updated.
42374242 updated = False
42384243 if isinstance (existing .node , TypeAlias ):
4239- if existing .node .target != res or existing . node . alias_tvars != alias_tvars :
4244+ if existing .node .target != res :
42404245 # Copy expansion to the existing alias, this matches how we update base classes
42414246 # for a TypeInfo _in place_ if there are nested placeholders.
42424247 existing .node .target = res
@@ -4250,6 +4255,8 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool:
42504255 # Otherwise just replace existing placeholder with type alias *in place*.
42514256 existing ._node = alias_node
42524257 updated = True
4258+ # TODO: switch type aliases to if has_placeholder(): process_placeholder() pattern.
4259+ # Type aliases are last notable exception from this logic.
42534260 if updated :
42544261 if self .final_iteration :
42554262 self .cannot_resolve_name (lvalue .name , "name" , s )
@@ -4773,6 +4780,7 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> bool:
47734780 n_values = call .arg_kinds [1 :].count (ARG_POS )
47744781 values = self .analyze_value_types (call .args [1 : 1 + n_values ])
47754782
4783+ # Reset fixed types both before and after each collection just in case.
47764784 self .types_fixed = None
47774785 res = self .process_typevar_parameters (
47784786 call .args [1 + n_values :],
@@ -5027,18 +5035,16 @@ def get_typevarlike_argument(
50275035 # class Custom(Generic[T]):
50285036 # ...
50295037 analyzed = PlaceholderType (None , [], context .line )
5030- if report_invalid_typevar_arg :
5031- if (
5032- isinstance (analyzed , ProperType )
5033- and isinstance (analyzed , AnyType )
5034- and analyzed .is_from_error
5035- ):
5036- self .fail (
5037- message_registry .TYPEVAR_ARG_MUST_BE_TYPE .format (
5038- typevarlike_name , param_name
5039- ),
5040- param_value ,
5041- )
5038+ if (
5039+ report_invalid_typevar_arg
5040+ and isinstance (analyzed , ProperType )
5041+ and isinstance (analyzed , AnyType )
5042+ and analyzed .is_from_error
5043+ ):
5044+ self .fail (
5045+ message_registry .TYPEVAR_ARG_MUST_BE_TYPE .format (typevarlike_name , param_name ),
5046+ param_value ,
5047+ )
50425048 # Note: we do not return 'None' here -- we want to continue
50435049 # using the AnyType.
50445050 return analyzed
@@ -5757,10 +5763,9 @@ def visit_type_alias_stmt(self, s: TypeAliasStmt) -> None:
57575763 self .mark_incomplete (s .name .name , s .value , becomes_typeinfo = True )
57585764 return
57595765
5760- # Now go through all new variables and temporary replace all tvars that still
5761- # refer to some placeholders. We defer the whole alias and will revisit it again,
5762- # as well as all its dependents.
57635766 if any (has_placeholder (tv ) for tv in alias_tvars ):
5767+ # Defer the alias if some type variables are not ready, same as for classes.
5768+ # Note: progress is forced below (if needed).
57645769 self .defer ()
57655770
57665771 self .add_type_alias_deps (depends_on )
0 commit comments