44
55import itertools
66from contextlib import contextmanager
7- from itertools import chain
87from typing import Callable , Iterable , Iterator , List , Sequence , Tuple , TypeVar
98from typing_extensions import Final , Protocol
109
@@ -203,8 +202,6 @@ def __init__(
203202 allow_type_any : bool = False ,
204203 ) -> None :
205204 self .api = api
206- self .lookup_qualified = api .lookup_qualified
207- self .lookup_fqn_func = api .lookup_fully_qualified
208205 self .fail_func = api .fail
209206 self .note_func = api .note
210207 self .tvar_scope = tvar_scope
@@ -244,6 +241,14 @@ def __init__(
244241 # Allow variables typed as Type[Any] and type (useful for base classes).
245242 self .allow_type_any = allow_type_any
246243
244+ def lookup_qualified (
245+ self , name : str , ctx : Context , suppress_errors : bool = False
246+ ) -> SymbolTableNode | None :
247+ return self .api .lookup_qualified (name , ctx , suppress_errors )
248+
249+ def lookup_fully_qualified (self , name : str ) -> SymbolTableNode :
250+ return self .api .lookup_fully_qualified (name )
251+
247252 def visit_unbound_type (self , t : UnboundType , defining_literal : bool = False ) -> Type :
248253 typ = self .visit_unbound_type_nonoptional (t , defining_literal )
249254 if t .optional :
@@ -1408,27 +1413,31 @@ def tvar_scope_frame(self) -> Iterator[None]:
14081413 yield
14091414 self .tvar_scope = old_scope
14101415
1416+ def find_type_var_likes (self , t : Type , include_callables : bool = True ) -> TypeVarLikeList :
1417+ return t .accept (
1418+ TypeVarLikeQuery (self .api , self .tvar_scope , include_callables = include_callables )
1419+ )
1420+
14111421 def infer_type_variables (self , type : CallableType ) -> list [tuple [str , TypeVarLikeExpr ]]:
14121422 """Return list of unique type variables referred to in a callable."""
14131423 names : list [str ] = []
14141424 tvars : list [TypeVarLikeExpr ] = []
14151425 for arg in type .arg_types :
1416- for name , tvar_expr in arg .accept (
1417- TypeVarLikeQuery (self .lookup_qualified , self .tvar_scope )
1418- ):
1426+ for name , tvar_expr in self .find_type_var_likes (arg ):
14191427 if name not in names :
14201428 names .append (name )
14211429 tvars .append (tvar_expr )
14221430 # When finding type variables in the return type of a function, don't
14231431 # look inside Callable types. Type variables only appearing in
14241432 # functions in the return type belong to those functions, not the
14251433 # function we're currently analyzing.
1426- for name , tvar_expr in type .ret_type .accept (
1427- TypeVarLikeQuery (self .lookup_qualified , self .tvar_scope , include_callables = False )
1428- ):
1434+ for name , tvar_expr in self .find_type_var_likes (type .ret_type , include_callables = False ):
14291435 if name not in names :
14301436 names .append (name )
14311437 tvars .append (tvar_expr )
1438+
1439+ if not names :
1440+ return [] # Fast path
14321441 return list (zip (names , tvars ))
14331442
14341443 def bind_function_type_variables (
@@ -1546,7 +1555,7 @@ def named_type(
15461555 line : int = - 1 ,
15471556 column : int = - 1 ,
15481557 ) -> Instance :
1549- node = self .lookup_fqn_func (fully_qualified_name )
1558+ node = self .lookup_fully_qualified (fully_qualified_name )
15501559 assert isinstance (node .node , TypeInfo )
15511560 any_type = AnyType (TypeOfAny .special_form )
15521561 if args is not None :
@@ -1785,7 +1794,9 @@ def set_any_tvars(
17851794 return TypeAliasType (node , [any_type ] * len (node .alias_tvars ), newline , newcolumn )
17861795
17871796
1788- def remove_dups (tvars : Iterable [T ]) -> list [T ]:
1797+ def remove_dups (tvars : list [T ]) -> list [T ]:
1798+ if len (tvars ) <= 1 :
1799+ return tvars
17891800 # Get unique elements in order of appearance
17901801 all_tvars : set [T ] = set ()
17911802 new_tvars : list [T ] = []
@@ -1796,26 +1807,29 @@ def remove_dups(tvars: Iterable[T]) -> list[T]:
17961807 return new_tvars
17971808
17981809
1799- def flatten_tvars (ll : Iterable [list [T ]]) -> list [T ]:
1800- return remove_dups (chain .from_iterable (ll ))
1810+ def flatten_tvars (lists : list [list [T ]]) -> list [T ]:
1811+ result : list [T ] = []
1812+ for lst in lists :
1813+ for item in lst :
1814+ if item not in result :
1815+ result .append (item )
1816+ return result
18011817
18021818
18031819class TypeVarLikeQuery (TypeQuery [TypeVarLikeList ]):
18041820 """Find TypeVar and ParamSpec references in an unbound type."""
18051821
18061822 def __init__ (
18071823 self ,
1808- lookup : Callable [[ str , Context ], SymbolTableNode | None ] ,
1824+ api : SemanticAnalyzerCoreInterface ,
18091825 scope : TypeVarLikeScope ,
18101826 * ,
18111827 include_callables : bool = True ,
1812- include_bound_tvars : bool = False ,
18131828 ) -> None :
1814- self .include_callables = include_callables
1815- self .lookup = lookup
1816- self .scope = scope
1817- self .include_bound_tvars = include_bound_tvars
18181829 super ().__init__ (flatten_tvars )
1830+ self .api = api
1831+ self .scope = scope
1832+ self .include_callables = include_callables
18191833 # Only include type variables in type aliases args. This would be anyway
18201834 # that case if we expand (as target variables would be overridden with args)
18211835 # and it may cause infinite recursion on invalid (diverging) recursive aliases.
@@ -1833,16 +1847,16 @@ def visit_unbound_type(self, t: UnboundType) -> TypeVarLikeList:
18331847 if name .endswith ("args" ):
18341848 if name .endswith (".args" ) or name .endswith (".kwargs" ):
18351849 base = "." .join (name .split ("." )[:- 1 ])
1836- n = self .lookup (base , t )
1850+ n = self .api . lookup_qualified (base , t )
18371851 if n is not None and isinstance (n .node , ParamSpecExpr ):
18381852 node = n
18391853 name = base
18401854 if node is None :
1841- node = self .lookup (name , t )
1855+ node = self .api . lookup_qualified (name , t )
18421856 if (
18431857 node
18441858 and isinstance (node .node , TypeVarLikeExpr )
1845- and ( self .include_bound_tvars or self . scope .get_binding (node ) is None )
1859+ and self .scope .get_binding (node ) is None
18461860 ):
18471861 assert isinstance (node .node , TypeVarLikeExpr )
18481862 return [(name , node .node )]
0 commit comments