1"""The abstract values used by vm.py. 2 3This file contains BaseValue and its subclasses. Mixins such as Class 4are in mixin.py, and other abstract logic is in abstract_utils.py. 5""" 6 7# Because pytype takes too long: 8# pytype: skip-file 9 10# Because of false positives: 11# pylint: disable=unpacking-non-sequence 12# pylint: disable=abstract-method 13 14import collections 15import contextlib 16import hashlib 17import inspect 18import itertools 19import logging 20from typing import Mapping 21 22from pytype import abstract_utils 23from pytype import class_mixin 24from pytype import datatypes 25from pytype import function 26from pytype import mixin 27from pytype import utils 28from pytype.pytd import escape 29from pytype.pytd import optimize 30from pytype.pytd import pytd 31from pytype.pytd import pytd_utils 32from pytype.pytd import visitors 33from pytype.pytd.codegen import decorate 34from pytype.typegraph import cfg 35from pytype.typegraph import cfg_utils 36 37log = logging.getLogger(__name__) 38 39 40class BaseValue(utils.VirtualMachineWeakrefMixin): 41 """A single abstract value such as a type or function signature. 42 43 This is the base class of the things that appear in Variables. It represents 44 an atomic object that the abstract interpreter works over just as variables 45 represent sets of parallel options. 46 47 Conceptually abstract values represent sets of possible concrete values in 48 compact form. For instance, an abstract value with .__class__ = int represents 49 all ints. 50 """ 51 52 formal = False # is this type non-instantiable? 53 54 def __init__(self, name, vm): 55 """Basic initializer for all BaseValues.""" 56 super().__init__(vm) 57 assert hasattr(vm, "program"), type(self) 58 self.cls = None 59 self.name = name 60 self.mro = self.compute_mro() 61 self.module = None 62 self.official_name = None 63 self.slots = None # writable attributes (or None if everything is writable) 64 # true for functions and classes that have decorators applied to them. 65 self.is_decorated = False 66 # The template for the current class. It is usually a constant, lazily 67 # loaded to accommodate recursive types, but in the case of typing.Generic 68 # (only), it'll change every time when a new generic class is instantiated. 69 self._template = None 70 # names in the templates of the current class and its base classes 71 self._all_template_names = None 72 self._instance = None 73 74 # The variable or function arg name with the type annotation that this 75 # instance was created from. For example, 76 # x: str = "hello" 77 # would create an instance of str with from_annotation = 'x' 78 self.from_annotation = None 79 80 @property 81 def all_template_names(self): 82 if self._all_template_names is None: 83 self._all_template_names = abstract_utils.get_template(self) 84 return self._all_template_names 85 86 @property 87 def template(self): 88 if self._template is None: 89 # Won't recompute if `compute_template` throws exception 90 self._template = () 91 self._template = abstract_utils.compute_template(self) 92 return self._template 93 94 @property 95 def full_name(self): 96 return (self.module + "." if self.module else "") + self.name 97 98 def __repr__(self): 99 return self.name 100 101 def compute_mro(self): 102 # default for objects with no MRO 103 return [] 104 105 def default_mro(self): 106 # default for objects with unknown MRO 107 return [self, self.vm.convert.object_type] 108 109 def get_fullhash(self): 110 """Hash this value and all of its children.""" 111 m = hashlib.md5() 112 seen_data = set() 113 stack = [self] 114 while stack: 115 data = stack.pop() 116 data_hash = hash(data) 117 if data_hash in seen_data: 118 continue 119 seen_data.add(data_hash) 120 m.update(str(data_hash).encode("utf-8")) 121 for mapping in data.get_children_maps(): 122 m.update(str(mapping.changestamp).encode("utf-8")) 123 stack.extend(mapping.data) 124 return m.digest() 125 126 def get_children_maps(self): 127 """Get this value's dictionaries of children. 128 129 Returns: 130 A sequence of dictionaries from names to child values. 131 """ 132 return () 133 134 def get_instance_type_parameter(self, name, node=None): 135 """Get a cfg.Variable of the instance's values for the type parameter. 136 137 Treating self as an abstract.Instance, gets the variable of its values for 138 the given type parameter. For the real implementation, see 139 SimpleValue.get_instance_type_parameter. 140 141 Args: 142 name: The name of the type parameter. 143 node: Optionally, the current CFG node. 144 Returns: 145 A Variable which may be empty. 146 """ 147 del name 148 if node is None: 149 node = self.vm.root_node 150 return self.vm.new_unsolvable(node) 151 152 def get_formal_type_parameter(self, t): 153 """Get the class's type for the type parameter. 154 155 Treating self as a class_mixin.Class, gets its formal type for the given 156 type parameter. For the real implementation, see 157 ParameterizedClass.get_formal_type_parameter. 158 159 Args: 160 t: The name of the type parameter. 161 Returns: 162 A formal type. 163 """ 164 del t 165 return self.vm.convert.unsolvable 166 167 def property_get(self, callself, is_class=False): 168 """Bind this value to the given self or cls. 169 170 This function is similar to __get__ except at the abstract level. This does 171 not trigger any code execution inside the VM. See __get__ for more details. 172 173 Args: 174 callself: The Variable that should be passed as self or cls when the call 175 is made. We only need one of self or cls, so having them share a 176 parameter prevents accidentally passing in both. 177 is_class: Whether callself is self or cls. Should be cls only when we 178 want to directly pass in a class to bind a class method to, rather than 179 passing in an instance and calling get_class(). 180 181 Returns: 182 Another abstract value that should be returned in place of this one. The 183 default implementation returns self, so this can always be called safely. 184 """ 185 del callself, is_class 186 return self 187 188 def get_special_attribute(self, unused_node, name, unused_valself): 189 """Fetch a special attribute (e.g., __get__, __iter__).""" 190 if name == "__class__": 191 if self.full_name == "typing.Protocol": 192 # Protocol.__class__ is a _ProtocolMeta class that inherits from 193 # abc.ABCMeta. Changing the definition of Protocol in typing.pytd to 194 # include this metaclass causes a bunch of weird breakages, so we 195 # instead return the metaclass when type() or __class__ is accessed on 196 # Protocol. For simplicity, we pretend the metaclass is ABCMeta rather 197 # than a subclass. 198 abc = self.vm.import_module("abc", "abc", 0).get_module("ABCMeta") 199 abc.load_lazy_attribute("ABCMeta") 200 return abc.members["ABCMeta"] 201 else: 202 return self.get_class().to_variable(self.vm.root_node) 203 return None 204 205 def get_own_new(self, node, value): 206 """Get this value's __new__ method, if it isn't object.__new__.""" 207 del value # Unused, only classes have methods. 208 return node, None 209 210 def call(self, node, func, args, alias_map=None): 211 """Call this abstract value with the given arguments. 212 213 The posargs and namedargs arguments may be modified by this function. 214 215 Args: 216 node: The CFGNode calling this function 217 func: The cfg.Binding containing this function. 218 args: Arguments for the call. 219 alias_map: A datatypes.UnionFind, which stores all the type renaming 220 information, mapping of type parameter name to its representative. 221 Returns: 222 A tuple (cfg.Node, cfg.Variable). The CFGNode corresponds 223 to the function's "return" statement(s). 224 Raises: 225 function.FailedFunctionCall 226 227 Make the call as required by this specific kind of atomic value, and make 228 sure to annotate the results correctly with the origins (val and also other 229 values appearing in the arguments). 230 """ 231 raise NotImplementedError(self.__class__.__name__) 232 233 def argcount(self, node): 234 """Returns the minimum number of arguments needed for a call.""" 235 raise NotImplementedError(self.__class__.__name__) 236 237 def register_instance(self, instance): # pylint: disable=unused-arg 238 """Treating self as a class definition, register an instance of it. 239 240 This is used for keeping merging call records on instances when generating 241 the formal definition of a class. See InterpreterClass and TupleClass. 242 243 Args: 244 instance: An instance of this class (as a BaseValue) 245 """ 246 247 def get_class(self): 248 """Return the class of this object. Equivalent of x.__class__ in Python.""" 249 raise NotImplementedError(self.__class__.__name__) 250 251 def get_instance_type(self, node=None, instance=None, seen=None, view=None): 252 """Get the type an instance of us would have.""" 253 return self.vm.convert.pytd_convert.value_instance_to_pytd_type( 254 node, self, instance, seen, view) 255 256 def to_type(self, node=None, seen=None, view=None): 257 """Get a PyTD type representing this object, as seen at a node.""" 258 return self.vm.convert.pytd_convert.value_to_pytd_type( 259 node, self, seen, view) 260 261 def to_pytd_def(self, node, name): 262 """Get a PyTD definition for this object.""" 263 return self.vm.convert.pytd_convert.value_to_pytd_def(node, self, name) 264 265 def get_default_type_key(self): 266 """Gets a default type key. See get_type_key.""" 267 return type(self) 268 269 def get_type_key(self, seen=None): # pylint: disable=unused-argument 270 """Build a key from the information used to perform type matching. 271 272 Get a hashable object containing this value's type information. Type keys 273 are only compared amongst themselves, so we don't care what the internals 274 look like, only that values with different types *always* have different 275 type keys and values with the same type preferably have the same type key. 276 277 Args: 278 seen: The set of values seen before while computing the type key. 279 280 Returns: 281 A hashable object built from this value's type information. 282 """ 283 return self.get_default_type_key() 284 285 def instantiate(self, node, container=None): 286 """Create an instance of self. 287 288 Note that this method does not call __init__, so the instance may be 289 incomplete. If you need a complete instance, use self.vm.init_class instead. 290 291 Args: 292 node: The current node. 293 container: Optionally, the value that contains self. (See TypeParameter.) 294 295 Returns: 296 The instance. 297 """ 298 return self._to_instance(container).to_variable(node) 299 300 def _to_instance(self, container): 301 return Instance(self, self.vm, container=container) 302 303 def to_annotation_container(self): 304 if isinstance(self, PyTDClass) and self.full_name == "builtins.tuple": 305 # If we are parameterizing builtins.tuple, replace it with typing.Tuple so 306 # that heterogeneous tuple annotations work. We need the isinstance() 307 # check to distinguish PyTDClass(tuple) from ParameterizedClass(tuple); 308 # the latter appears here when a generic type alias is being substituted. 309 typing = self.vm.import_module("typing", "typing", 0).get_module("Tuple") 310 typing.load_lazy_attribute("Tuple") 311 return abstract_utils.get_atomic_value(typing.members["Tuple"]) 312 return AnnotationContainer(self.name, self.vm, self) 313 314 def to_variable(self, node): 315 """Build a variable out of this abstract value. 316 317 Args: 318 node: The current CFG node. 319 Returns: 320 A cfg.Variable. 321 """ 322 return self.vm.program.NewVariable([self], source_set=[], where=node) 323 324 def to_binding(self, node): 325 binding, = self.to_variable(node).bindings 326 return binding 327 328 def has_varargs(self): 329 """Return True if this is a function and has a *args parameter.""" 330 return False 331 332 def has_kwargs(self): 333 """Return True if this is a function and has a **kwargs parameter.""" 334 return False 335 336 def _unique_parameters(self): 337 """Get unique parameter subtypes as variables. 338 339 This will retrieve 'children' of this value that contribute to the 340 type of it. So it will retrieve type parameters, but not attributes. To 341 keep the number of possible combinations reasonable, when we encounter 342 multiple instances of the same type, we include only one. 343 344 Returns: 345 A list of variables. 346 """ 347 return [] 348 349 def unique_parameter_values(self): 350 """Get unique parameter subtypes as bindings. 351 352 Like _unique_parameters, but returns bindings instead of variables. 353 354 Returns: 355 A list of list of bindings. 356 """ 357 # TODO(rechen): Remember which values were merged under which type keys so 358 # we don't have to recompute this information in match_value_against_type. 359 def _get_values(parameter): 360 return {b.data.get_type_key(): b for b in parameter.bindings}.values() 361 return [_get_values(parameter) for parameter in self._unique_parameters()] 362 363 def init_subclass(self, node, cls): 364 """Allow metaprogramming via __init_subclass__. 365 366 We do not analyse __init_subclass__ methods in the code, but overlays that 367 wish to replicate metaprogramming constructs using __init_subclass__ can 368 define a class overriding this method, and vm.make_class will call 369 Class.call_init_subclass(), which will invoke the init_subclass() method for 370 all classes in the list of base classes. 371 372 This is here rather than in class_mixin.Class because a class's list of 373 bases can include abstract objects that do not derive from Class (e.g. 374 Unknown and Unsolvable). 375 376 Args: 377 node: cfg node 378 cls: the abstract.InterpreterClass that is being constructed with subclass 379 as a base 380 Returns: 381 A possibly new cfg node 382 """ 383 del cls 384 return node 385 386 def update_official_name(self, _): 387 """Update the official name.""" 388 389 # The below methods allow code to do isinstance() checks on abstract values 390 # without importing abstract.py, making it easier to avoid import cycles. 391 392 def isinstance_AMBIGUOUS_OR_EMPTY(self): 393 return isinstance(self, AMBIGUOUS_OR_EMPTY) 394 395 def isinstance_AnnotationClass(self): 396 return isinstance(self, AnnotationClass) 397 398 def isinstance_AnnotationsDict(self): 399 return isinstance(self, AnnotationsDict) 400 401 def isinstance_BoundFunction(self): 402 return isinstance(self, BoundFunction) 403 404 def isinstance_Class(self): 405 return isinstance(self, class_mixin.Class) 406 407 def isinstance_ClassMethod(self): 408 return isinstance(self, ClassMethod) 409 410 def isinstance_ClassMethodInstance(self): 411 return False # overridden in special_builtins.ClassMethodInstance 412 413 def isinstance_Dict(self): 414 return isinstance(self, Dict) 415 416 def isinstance_Function(self): 417 return isinstance(self, Function) 418 419 def isinstance_Instance(self): 420 return isinstance(self, Instance) 421 422 def isinstance_InterpreterClass(self): 423 return isinstance(self, InterpreterClass) 424 425 def isinstance_InterpreterFunction(self): 426 return isinstance(self, InterpreterFunction) 427 428 def isinstance_List(self): 429 return isinstance(self, List) 430 431 def isinstance_LiteralClass(self): 432 return isinstance(self, LiteralClass) 433 434 def isinstance_ParameterizedClass(self): 435 return isinstance(self, ParameterizedClass) 436 437 def isinstance_PropertyInstance(self): 438 return False # overridden in special_builtins.PropertyInstance 439 440 def isinstance_PyTDClass(self): 441 return isinstance(self, PyTDClass) 442 443 def isinstance_PyTDFunction(self): 444 return isinstance(self, PyTDFunction) 445 446 def isinstance_PythonConstant(self): 447 return isinstance(self, mixin.PythonConstant) 448 449 def isinstance_SignedFunction(self): 450 return isinstance(self, SignedFunction) 451 452 def isinstance_SimpleFunction(self): 453 return isinstance(self, SimpleFunction) 454 455 def isinstance_SimpleValue(self): 456 return isinstance(self, SimpleValue) 457 458 def isinstance_Splat(self): 459 return isinstance(self, Splat) 460 461 def isinstance_StaticMethod(self): 462 return isinstance(self, StaticMethod) 463 464 def isinstance_StaticMethodInstance(self): 465 return False # overridden in special_builtins.StaticMethodInstance 466 467 def isinstance_Tuple(self): 468 return isinstance(self, Tuple) 469 470 def isinstance_TypeParameter(self): 471 return isinstance(self, TypeParameter) 472 473 def isinstance_TypeParameterInstance(self): 474 return isinstance(self, TypeParameterInstance) 475 476 def isinstance_Union(self): 477 return isinstance(self, Union) 478 479 def isinstance_Unknown(self): 480 return isinstance(self, Unknown) 481 482 def isinstance_Unsolvable(self): 483 return isinstance(self, Unsolvable) 484 485 def is_late_annotation(self): 486 return False 487 488 489class Singleton(BaseValue): 490 """A Singleton class must only be instantiated once. 491 492 This is essentially an ABC for Unsolvable, Empty, and others. 493 """ 494 495 _instance = None 496 497 def __new__(cls, *args, **kwargs): 498 # If cls is a subclass of a subclass of Singleton, cls._instance will be 499 # filled by its parent. cls needs to be given its own instance. 500 if not cls._instance or type(cls._instance) != cls: # pylint: disable=unidiomatic-typecheck 501 log.debug("Singleton: Making new instance for %s", cls) 502 cls._instance = super().__new__(cls) 503 return cls._instance 504 505 def get_special_attribute(self, node, name, valself): 506 del name, valself 507 return self.to_variable(node) 508 509 def compute_mro(self): 510 return self.default_mro() 511 512 def call(self, node, func, args, alias_map=None): 513 del func, args 514 return node, self.to_variable(node) 515 516 def get_class(self): 517 return self 518 519 def instantiate(self, node, container=None): 520 return self.to_variable(node) 521 522 523class Empty(Singleton): 524 """An empty value. 525 526 These values represent items extracted from empty containers. Because of false 527 positives in flagging containers as empty (consider: 528 x = [] 529 def initialize(): 530 populate(x) 531 def f(): 532 iterate(x) 533 ), we treat these values as placeholders that we can do anything with, similar 534 to Unsolvable, with the difference that they eventually convert to 535 NothingType so that cases in which they are truly empty are discarded (see: 536 x = ... # type: List[nothing] or Dict[int, str] 537 y = [i for i in x] # The type of i is int; y is List[int] 538 ). On the other hand, if Empty is the sole type candidate, we assume that the 539 container was populated elsewhere: 540 x = [] 541 def initialize(): 542 populate(x) 543 def f(): 544 return x[0] # Oops! The return type should be Any rather than nothing. 545 The nothing -> anything conversion happens in 546 convert.Converter._function_to_def and analyze.CallTracer.pytd_for_types. 547 """ 548 549 def __init__(self, vm): 550 super().__init__("empty", vm) 551 552 553class Deleted(Empty): 554 """Assigned to variables that have del called on them.""" 555 556 def __init__(self, vm): 557 super().__init__(vm) 558 self.name = "deleted" 559 560 def get_special_attribute(self, node, name, valself): 561 del name, valself # unused 562 return self.vm.new_unsolvable(node) 563 564 565class TypeParameter(BaseValue): 566 """Parameter of a type.""" 567 568 formal = True 569 570 def __init__(self, name, vm, constraints=(), bound=None, 571 covariant=False, contravariant=False, module=None): 572 super().__init__(name, vm) 573 self.constraints = constraints 574 self.bound = bound 575 self.covariant = covariant 576 self.contravariant = contravariant 577 self.module = module 578 579 def is_generic(self): 580 return not self.constraints and not self.bound 581 582 def copy(self): 583 return TypeParameter(self.name, self.vm, self.constraints, self.bound, 584 self.covariant, self.contravariant, self.module) 585 586 def with_module(self, module): 587 res = self.copy() 588 res.module = module 589 return res 590 591 def __eq__(self, other): 592 if isinstance(other, type(self)): 593 return (self.name == other.name and 594 self.constraints == other.constraints and 595 self.bound == other.bound and 596 self.covariant == other.covariant and 597 self.contravariant == other.contravariant and 598 self.module == other.module) 599 return NotImplemented 600 601 def __ne__(self, other): 602 return not self == other 603 604 def __hash__(self): 605 return hash((self.name, self.constraints, self.bound, self.covariant, 606 self.contravariant)) 607 608 def __repr__(self): 609 return "TypeParameter(%r, constraints=%r, bound=%r, module=%r)" % ( 610 self.name, self.constraints, self.bound, self.module) 611 612 def instantiate(self, node, container=None): 613 var = self.vm.program.NewVariable() 614 if container and (not isinstance(container, SimpleValue) or 615 self.full_name in container.all_template_names): 616 instance = TypeParameterInstance(self, container, self.vm) 617 return instance.to_variable(node) 618 else: 619 for c in self.constraints: 620 var.PasteVariable(c.instantiate(node, container)) 621 if self.bound: 622 var.PasteVariable(self.bound.instantiate(node, container)) 623 if not var.bindings: 624 var.AddBinding(self.vm.convert.unsolvable, [], node) 625 return var 626 627 def update_official_name(self, name): 628 if self.name != name: 629 message = "TypeVar(%r) must be stored as %r, not %r" % ( 630 self.name, self.name, name) 631 self.vm.errorlog.invalid_typevar(self.vm.frames, message) 632 633 def get_class(self): 634 return self 635 636 def call(self, node, func, args, alias_map=None): 637 return node, self.instantiate(node) 638 639 640class TypeParameterInstance(BaseValue): 641 """An instance of a type parameter.""" 642 643 def __init__(self, param, instance, vm): 644 super().__init__(param.name, vm) 645 self.param = param 646 self.instance = instance 647 self.module = param.module 648 649 def get_class(self): 650 return self.param 651 652 def call(self, node, func, args, alias_map=None): 653 var = self.instance.get_instance_type_parameter(self.name) 654 if var.bindings: 655 return self.vm.call_function(node, var, args) 656 else: 657 return node, self.vm.convert.empty.to_variable(self.vm.root_node) 658 659 def __repr__(self): 660 return "TypeParameterInstance(%r)" % self.name 661 662 def __eq__(self, other): 663 if isinstance(other, type(self)): 664 return self.param == other.param and self.instance == other.instance 665 return NotImplemented 666 667 def __hash__(self): 668 return hash((self.param, self.instance)) 669 670 671class SimpleValue(BaseValue): 672 """A basic abstract value that represents instances. 673 674 This class implements instances in the Python sense. Instances of the same 675 class may vary. 676 677 Note that the cls attribute will point to another abstract value that 678 represents the class object itself, not to some special type representation. 679 680 Attributes: 681 members: A name->value dictionary of the instance's attributes. 682 """ 683 684 def __init__(self, name, vm): 685 """Initialize a SimpleValue. 686 687 Args: 688 name: Name of this value. For debugging and error reporting. 689 vm: The TypegraphVirtualMachine to use. 690 """ 691 super().__init__(name, vm) 692 self.members = datatypes.MonitorDict() 693 # Lazily loaded to handle recursive types. 694 # See Instance._load_instance_type_parameters(). 695 self._instance_type_parameters = datatypes.AliasingMonitorDict() 696 # This attribute depends on self.cls, which isn't yet set to its true value. 697 self._maybe_missing_members = None 698 # The latter caches the result of get_type_key. This is a recursive function 699 # that has the potential to generate too many calls for large definitions. 700 self._cached_type_key = ( 701 (self.members.changestamp, self._instance_type_parameters.changestamp), 702 None) 703 704 @property 705 def instance_type_parameters(self): 706 return self._instance_type_parameters 707 708 @property 709 def maybe_missing_members(self): 710 if self._maybe_missing_members is None: 711 self._maybe_missing_members = isinstance( 712 self.cls, (InterpreterClass, PyTDClass)) and self.cls.is_dynamic 713 return self._maybe_missing_members 714 715 @maybe_missing_members.setter 716 def maybe_missing_members(self, v): 717 self._maybe_missing_members = v 718 719 def has_instance_type_parameter(self, name): 720 """Check if the key is in `instance_type_parameters`.""" 721 name = abstract_utils.full_type_name(self, name) 722 return name in self.instance_type_parameters 723 724 def get_children_maps(self): 725 return (self.instance_type_parameters, self.members) 726 727 def get_instance_type_parameter(self, name, node=None): 728 name = abstract_utils.full_type_name(self, name) 729 param = self.instance_type_parameters.get(name) 730 if not param: 731 log.info("Creating new empty type param %s", name) 732 if node is None: 733 node = self.vm.root_node 734 param = self.vm.program.NewVariable([], [], node) 735 self.instance_type_parameters[name] = param 736 return param 737 738 def merge_instance_type_parameter(self, node, name, value): 739 """Set the value of a type parameter. 740 741 This will always add to the type parameter unlike set_attribute which will 742 replace value from the same basic block. This is because type parameters may 743 be affected by a side effect so we need to collect all the information 744 regardless of multiple assignments in one basic block. 745 746 Args: 747 node: Optionally, the current CFG node. 748 name: The name of the type parameter. 749 value: The value that is being used for this type parameter as a Variable. 750 """ 751 name = abstract_utils.full_type_name(self, name) 752 log.info("Modifying type param %s", name) 753 if name in self.instance_type_parameters: 754 self.instance_type_parameters[name].PasteVariable(value, node) 755 else: 756 self.instance_type_parameters[name] = value 757 758 def call(self, node, _, args, alias_map=None): 759 node, var = self.vm.attribute_handler.get_attribute( 760 node, self, "__call__", self.to_binding(node)) 761 if var is not None and var.bindings: 762 return self.vm.call_function(node, var, args) 763 else: 764 raise function.NotCallable(self) 765 766 def argcount(self, node): 767 node, var = self.vm.attribute_handler.get_attribute( 768 node, self, "__call__", self.to_binding(node)) 769 if var and var.bindings: 770 return min(v.argcount(node) for v in var.data) 771 else: 772 # It doesn't matter what we return here, since any attempt to call this 773 # value will lead to a not-callable error anyways. 774 return 0 775 776 def __repr__(self): 777 cls = " [%r]" % self.cls if self.cls else "" 778 return "<%s%s>" % (self.name, cls) 779 780 def get_class(self): 781 # See Py_TYPE() in Include/object.h 782 if self.cls: 783 return self.cls 784 elif isinstance(self, InterpreterClass): 785 return ParameterizedClass( 786 self.vm.convert.type_type, {abstract_utils.T: self}, self.vm) 787 elif isinstance(self, (AnnotationClass, class_mixin.Class)): 788 return self.vm.convert.type_type 789 790 def set_class(self, node, var): 791 """Set the __class__ of an instance, for code that does "x.__class__ = y.""" 792 # Simplification: Setting __class__ is done rarely, and supporting this 793 # action would complicate pytype considerably by forcing us to track the 794 # class in a variable, so we instead fall back to Any. 795 try: 796 new_cls = abstract_utils.get_atomic_value(var) 797 except abstract_utils.ConversionError: 798 self.cls = self.vm.convert.unsolvable 799 else: 800 if self.cls and self.cls != new_cls: 801 self.cls = self.vm.convert.unsolvable 802 else: 803 self.cls = new_cls 804 new_cls.register_instance(self) 805 return node 806 807 def get_type_key(self, seen=None): 808 cached_changestamps, saved_key = self._cached_type_key 809 if saved_key and cached_changestamps == ( 810 self.members.changestamp, 811 self.instance_type_parameters.changestamp): 812 return saved_key 813 if not seen: 814 seen = set() 815 seen.add(self) 816 key = set() 817 if self.cls: 818 key.add(self.cls) 819 for name, var in self.instance_type_parameters.items(): 820 subkey = frozenset( 821 value.data.get_default_type_key() # pylint: disable=g-long-ternary 822 if value.data in seen else value.data.get_type_key(seen) 823 for value in var.bindings) 824 key.add((name, subkey)) 825 if key: 826 type_key = frozenset(key) 827 else: 828 type_key = super().get_type_key() 829 self._cached_type_key = ( 830 (self.members.changestamp, self.instance_type_parameters.changestamp), 831 type_key) 832 return type_key 833 834 def _unique_parameters(self): 835 parameters = super()._unique_parameters() 836 parameters.extend(self.instance_type_parameters.values()) 837 return parameters 838 839 840class Instance(SimpleValue): 841 """An instance of some object.""" 842 843 def __init__(self, cls, vm, container=None): 844 super().__init__(cls.name, vm) 845 self.cls = cls 846 self._instance_type_parameters_loaded = False 847 self._container = container 848 cls.register_instance(self) 849 850 def _load_instance_type_parameters(self): 851 if self._instance_type_parameters_loaded: 852 return 853 all_formal_type_parameters = datatypes.AliasingMonitorDict() 854 abstract_utils.parse_formal_type_parameters( 855 self.cls, None, all_formal_type_parameters, self._container) 856 self._instance_type_parameters.uf = all_formal_type_parameters.uf 857 for name, param in all_formal_type_parameters.items(): 858 if param is None: 859 value = self.vm.program.NewVariable() 860 log.info("Initializing type param %s: %r", name, value) 861 self._instance_type_parameters[name] = value 862 else: 863 self._instance_type_parameters[name] = param.instantiate( 864 self.vm.root_node, self._container or self) 865 # We purposely set this flag at the very end so that accidentally accessing 866 # instance_type_parameters during loading will trigger an obvious crash due 867 # to infinite recursion, rather than silently returning an incomplete dict. 868 self._instance_type_parameters_loaded = True 869 870 @property 871 def full_name(self): 872 return self.get_class().full_name 873 874 @property 875 def instance_type_parameters(self): 876 self._load_instance_type_parameters() 877 return self._instance_type_parameters 878 879 880class List(Instance, mixin.HasSlots, mixin.PythonConstant): 881 """Representation of Python 'list' objects.""" 882 883 def __init__(self, content, vm): 884 super().__init__(vm.convert.list_type, vm) 885 self._instance_cache = {} 886 mixin.PythonConstant.init_mixin(self, content) 887 mixin.HasSlots.init_mixin(self) 888 combined_content = vm.convert.build_content(content) 889 self.merge_instance_type_parameter(None, abstract_utils.T, combined_content) 890 self.could_contain_anything = False 891 self.set_slot("__getitem__", self.getitem_slot) 892 self.set_slot("__getslice__", self.getslice_slot) 893 894 def str_of_constant(self, printer): 895 return "[%s]" % ", ".join(" or ".join(abstract_utils.var_map(printer, val)) 896 for val in self.pyval) 897 898 def __repr__(self): 899 if self.could_contain_anything: 900 return Instance.__repr__(self) 901 else: 902 return mixin.PythonConstant.__repr__(self) 903 904 def merge_instance_type_parameter(self, node, name, value): 905 self.could_contain_anything = True 906 super().merge_instance_type_parameter(node, name, value) 907 908 def getitem_slot(self, node, index_var): 909 """Implements __getitem__ for List. 910 911 Arguments: 912 node: The current CFG node. 913 index_var: The Variable containing the index value, the i in lst[i]. 914 915 Returns: 916 Tuple of (node, return_variable). node may be the same as the argument. 917 return_variable is a Variable with bindings of the possible return values. 918 """ 919 results = [] 920 unresolved = False 921 node, ret = self.call_pytd(node, "__getitem__", index_var) 922 if not self.could_contain_anything: 923 for val in index_var.bindings: 924 try: 925 index = self.vm.convert.value_to_constant(val.data, int) 926 except abstract_utils.ConversionError: 927 unresolved = True 928 else: 929 self_len = len(self.pyval) 930 if -self_len <= index < self_len: 931 results.append(self.pyval[index]) 932 else: 933 unresolved = True 934 if unresolved or self.could_contain_anything: 935 results.append(ret) 936 return node, self.vm.join_variables(node, results) 937 938 def _get_index(self, data): 939 """Helper function for getslice_slot that extracts int or None from data. 940 941 If data is an Instance of int, None is returned. 942 943 Args: 944 data: The object to extract from. Usually a ConcreteValue or an 945 Instance. 946 947 Returns: 948 The value (an int or None) of the index. 949 950 Raises: 951 abstract_utils.ConversionError: If the data could not be converted. 952 """ 953 if isinstance(data, ConcreteValue): 954 return self.vm.convert.value_to_constant(data, (int, type(None))) 955 elif isinstance(data, Instance): 956 if data.cls != self.vm.convert.int_type: 957 raise abstract_utils.ConversionError() 958 else: 959 return None 960 else: 961 raise abstract_utils.ConversionError() 962 963 def getslice_slot(self, node, start_var, end_var): 964 """Implements __getslice__ for List. 965 966 Arguments: 967 node: The current CFG node. 968 start_var: A Variable containing the i in lst[i:j]. 969 end_var: A Variable containing the j in lst[i:j]. 970 971 Returns: 972 Tuple of (node, return_variable). node may be the same as the argument. 973 return_variable is a Variable with bindings of the possible return values. 974 """ 975 # call_pytd will typecheck start_var and end_var. 976 node, ret = self.call_pytd(node, "__getslice__", start_var, end_var) 977 results = [] 978 unresolved = False 979 if not self.could_contain_anything: 980 for start_val, end_val in cfg_utils.variable_product([start_var, 981 end_var]): 982 try: 983 start = self._get_index(start_val.data) 984 end = self._get_index(end_val.data) 985 except abstract_utils.ConversionError: 986 unresolved = True 987 else: 988 results.append(List(self.pyval[start:end], self.vm).to_variable(node)) 989 if unresolved or self.could_contain_anything: 990 results.append(ret) 991 return node, self.vm.join_variables(node, results) 992 993 994class Tuple(Instance, mixin.PythonConstant): 995 """Representation of Python 'tuple' objects.""" 996 997 def __init__(self, content, vm): 998 combined_content = vm.convert.build_content(content) 999 class_params = { 1000 name: vm.convert.merge_classes(instance_param.data) 1001 for name, instance_param in 1002 tuple(enumerate(content)) + ((abstract_utils.T, combined_content),)} 1003 cls = TupleClass(vm.convert.tuple_type, class_params, vm) 1004 super().__init__(cls, vm) 1005 self.merge_instance_type_parameter(None, abstract_utils.T, combined_content) 1006 mixin.PythonConstant.init_mixin(self, content) 1007 self.tuple_length = len(self.pyval) 1008 self._hash = None # memoized due to expensive computation 1009 # set this to true when creating a function arg tuple 1010 self.is_unpacked_function_args = False 1011 1012 def str_of_constant(self, printer): 1013 content = ", ".join(" or ".join(abstract_utils.var_map(printer, val)) 1014 for val in self.pyval) 1015 if self.tuple_length == 1: 1016 content += "," 1017 return "(%s)" % content 1018 1019 def _unique_parameters(self): 1020 parameters = super()._unique_parameters() 1021 parameters.extend(self.pyval) 1022 return parameters 1023 1024 def __eq__(self, other): 1025 if isinstance(other, type(self)): 1026 return (self.tuple_length == other.tuple_length and 1027 all(e.data == other_e.data 1028 for e, other_e in zip(self.pyval, other.pyval))) 1029 return NotImplemented 1030 1031 def __hash__(self): 1032 if self._hash is None: 1033 # Descending into pyval would trigger infinite recursion in the case of a 1034 # tuple containing itself, so we approximate the inner values with their 1035 # full names. 1036 approximate_hash = lambda var: tuple(v.full_name for v in var.data) 1037 self._hash = hash((self.tuple_length,) + 1038 tuple(approximate_hash(e) for e in self.pyval)) 1039 return self._hash 1040 1041 1042class Dict(Instance, mixin.HasSlots, mixin.PythonDict): 1043 """Representation of Python 'dict' objects. 1044 1045 It works like builtins.dict, except that, for string keys, it keeps track 1046 of what got stored. 1047 """ 1048 1049 def __init__(self, vm): 1050 super().__init__(vm.convert.dict_type, vm) 1051 mixin.HasSlots.init_mixin(self) 1052 self.set_slot("__contains__", self.contains_slot) 1053 self.set_slot("__getitem__", self.getitem_slot) 1054 self.set_slot("__setitem__", self.setitem_slot) 1055 self.set_slot("pop", self.pop_slot) 1056 self.set_slot("setdefault", self.setdefault_slot) 1057 self.set_slot("update", self.update_slot) 1058 self.could_contain_anything = False 1059 # Use OrderedDict instead of dict, so that it can be compatible with 1060 # where needs ordered dict. 1061 # For example: f_locals["__annotations__"] 1062 mixin.PythonDict.init_mixin(self, collections.OrderedDict()) 1063 1064 def str_of_constant(self, printer): 1065 return str({name: " or ".join(abstract_utils.var_map(printer, value)) 1066 for name, value in self.pyval.items()}) 1067 1068 def __repr__(self): 1069 if not hasattr(self, "could_contain_anything"): 1070 return "Dict (not fully initialized)" 1071 elif self.could_contain_anything: 1072 return Instance.__repr__(self) 1073 else: 1074 return mixin.PythonConstant.__repr__(self) 1075 1076 def getitem_slot(self, node, name_var): 1077 """Implements the __getitem__ slot.""" 1078 results = [] 1079 unresolved = False 1080 if not self.could_contain_anything: 1081 for val in name_var.bindings: 1082 try: 1083 name = self.vm.convert.value_to_constant(val.data, str) 1084 except abstract_utils.ConversionError: 1085 unresolved = True 1086 else: 1087 try: 1088 results.append(self.pyval[name]) 1089 except KeyError as e: 1090 unresolved = True 1091 raise function.DictKeyMissing(name) from e 1092 node, ret = self.call_pytd(node, "__getitem__", name_var) 1093 if unresolved or self.could_contain_anything: 1094 # We *do* know the overall type of the values through the "V" type 1095 # parameter, even if we don't know the exact type of self[name]. So let's 1096 # just use the (less accurate) value from pytd. 1097 results.append(ret) 1098 return node, self.vm.join_variables(node, results) 1099 1100 def set_str_item(self, node, name, value_var): 1101 self.merge_instance_type_parameter( 1102 node, abstract_utils.K, self.vm.convert.build_string(node, name)) 1103 self.merge_instance_type_parameter(node, abstract_utils.V, value_var) 1104 if name in self.pyval: 1105 self.pyval[name].PasteVariable(value_var, node) 1106 else: 1107 self.pyval[name] = value_var 1108 return node 1109 1110 def setitem(self, node, name_var, value_var): 1111 assert isinstance(name_var, cfg.Variable) 1112 assert isinstance(value_var, cfg.Variable) 1113 for val in name_var.bindings: 1114 try: 1115 name = self.vm.convert.value_to_constant(val.data, str) 1116 except abstract_utils.ConversionError: 1117 # Now the dictionary is abstract: We don't know what it contains 1118 # anymore. Note that the below is not a variable, so it'll affect 1119 # all branches. 1120 self.could_contain_anything = True 1121 continue 1122 if name in self.pyval: 1123 self.pyval[name].PasteVariable(value_var, node) 1124 else: 1125 self.pyval[name] = value_var 1126 1127 def setitem_slot(self, node, name_var, value_var): 1128 """Implements the __setitem__ slot.""" 1129 self.setitem(node, name_var, value_var) 1130 return self.call_pytd(node, "__setitem__", name_var, value_var) 1131 1132 def setdefault_slot(self, node, name_var, value_var=None): 1133 if value_var is None: 1134 value_var = self.vm.convert.build_none(node) 1135 # We don't have a good way of modelling the exact setdefault behavior - 1136 # whether the key already exists might depend on a code path, so setting it 1137 # again should depend on an if-splitting condition, but we don't support 1138 # negative conditions. 1139 self.setitem(node, name_var, value_var) 1140 return self.call_pytd(node, "setdefault", name_var, value_var) 1141 1142 def contains_slot(self, node, key_var): 1143 if self.could_contain_anything: 1144 value = None 1145 else: 1146 try: 1147 str_key = abstract_utils.get_atomic_python_constant(key_var, str) 1148 except abstract_utils.ConversionError: 1149 value = None 1150 else: 1151 value = str_key in self.pyval 1152 return node, self.vm.convert.build_bool(node, value) 1153 1154 def pop_slot(self, node, key_var, default_var=None): 1155 try: 1156 str_key = abstract_utils.get_atomic_python_constant(key_var, str) 1157 except abstract_utils.ConversionError: 1158 self.could_contain_anything = True 1159 if self.could_contain_anything: 1160 if default_var: 1161 return self.call_pytd(node, "pop", key_var, default_var) 1162 else: 1163 return self.call_pytd(node, "pop", key_var) 1164 if default_var: 1165 return node, self.pyval.pop(str_key, default_var) 1166 else: 1167 try: 1168 return node, self.pyval.pop(str_key) 1169 except KeyError as e: 1170 raise function.DictKeyMissing(str_key) from e 1171 1172 def update_slot(self, node, *args, **kwargs): 1173 posargs_handled = False 1174 if len(args) == 1: 1175 arg_data = args[0].data 1176 if len(arg_data) == 1: 1177 self.update(node, arg_data[0]) 1178 posargs_handled = True 1179 elif not args: 1180 posargs_handled = True 1181 self.update(node, kwargs) 1182 if not posargs_handled: 1183 self.could_contain_anything = True 1184 return self.call_pytd(node, "update", *args) 1185 else: 1186 return node, self.vm.convert.none.to_variable(node) 1187 1188 def update(self, node, other_dict, omit=()): 1189 if isinstance(other_dict, (Dict, dict)): 1190 for key, value in other_dict.items(): 1191 if key not in omit: 1192 self.set_str_item(node, key, value) 1193 if isinstance(other_dict, Dict): 1194 k = other_dict.get_instance_type_parameter(abstract_utils.K, node) 1195 v = other_dict.get_instance_type_parameter(abstract_utils.V, node) 1196 self.merge_instance_type_parameter(node, abstract_utils.K, k) 1197 self.merge_instance_type_parameter(node, abstract_utils.V, v) 1198 self.could_contain_anything |= other_dict.could_contain_anything 1199 else: 1200 assert isinstance(other_dict, BaseValue) 1201 if (isinstance(other_dict, Instance) and 1202 other_dict.full_name == "builtins.dict"): 1203 k = other_dict.get_instance_type_parameter(abstract_utils.K, node) 1204 v = other_dict.get_instance_type_parameter(abstract_utils.V, node) 1205 else: 1206 k = v = self.vm.new_unsolvable(node) 1207 self.merge_instance_type_parameter(node, abstract_utils.K, k) 1208 self.merge_instance_type_parameter(node, abstract_utils.V, v) 1209 self.could_contain_anything = True 1210 1211 1212class AnnotationsDict(Dict): 1213 """__annotations__ dict.""" 1214 1215 def __init__(self, annotated_locals, vm): 1216 super().__init__(vm) 1217 self.annotated_locals = annotated_locals 1218 1219 def get_type(self, node, name): 1220 if name not in self.annotated_locals: 1221 return None 1222 return self.annotated_locals[name].get_type(node, name) 1223 1224 def get_annotations(self, node): 1225 for name, local in self.annotated_locals.items(): 1226 typ = local.get_type(node, name) 1227 if typ: 1228 yield name, typ 1229 1230 def __repr__(self): 1231 return repr(self.annotated_locals) 1232 1233 1234class LateAnnotation: 1235 """A late annotation. 1236 1237 A late annotation stores a string expression and a snapshot of the VM stack at 1238 the point where the annotation was introduced. Once the expression is 1239 resolved, the annotation pretends to be the resolved type; before that, it 1240 pretends to be an unsolvable. This effect is achieved by delegating attribute 1241 lookup with __getattribute__. 1242 1243 Note that for late annotation x, `isinstance(x, ...)` and `x.__class__` will 1244 use the type that x is pretending to be; `type(x)` will reveal x's true type. 1245 Use `x.is_late_annotation()` to check whether x is a late annotation. 1246 """ 1247 1248 def __init__(self, expr, stack, vm): 1249 self.expr = expr 1250 self.stack = stack 1251 self.vm = vm 1252 self.resolved = False 1253 self._type = vm.convert.unsolvable # the resolved type of `expr` 1254 self._unresolved_instances = set() 1255 # _attribute_names needs to be defined last! 1256 self._attribute_names = ( 1257 set(LateAnnotation.__dict__) | 1258 set(super().__getattribute__("__dict__"))) 1259 1260 def __repr__(self): 1261 return "LateAnnotation(%r, resolved=%r)" % ( 1262 self.expr, self._type if self.resolved else None) 1263 1264 # __hash__ and __eq__ need to be explicitly defined for Python to use them in 1265 # set/dict comparisons. 1266 1267 def __hash__(self): 1268 return hash(self._type) if self.resolved else hash(self.expr) 1269 1270 def __eq__(self, other): 1271 return hash(self) == hash(other) 1272 1273 def __getattribute__(self, name): 1274 if name == "_attribute_names" or name in self._attribute_names: 1275 return super().__getattribute__(name) 1276 return self._type.__getattribute__(name) 1277 1278 def resolve(self, node, f_globals, f_locals): 1279 """Resolve the late annotation.""" 1280 if self.resolved: 1281 return 1282 self.resolved = True 1283 var, errorlog = abstract_utils.eval_expr( 1284 self.vm, node, f_globals, f_locals, self.expr) 1285 if errorlog: 1286 self.vm.errorlog.copy_from(errorlog.errors, self.stack) 1287 self._type = self.vm.annotations_util.extract_annotation( 1288 node, var, None, self.stack) 1289 if self._type != self.vm.convert.unsolvable: 1290 # We may have tried to call __init__ on instances of this annotation. 1291 # Since the annotation was unresolved at the time, we need to call 1292 # __init__ again to define any instance attributes. 1293 for instance in self._unresolved_instances: 1294 if isinstance(instance.cls, Union): 1295 # Having instance.cls be a Union type will crash in attribute.py. 1296 # Setting it to Any picks up the annotation in another code path. 1297 instance.cls = self.vm.convert.unsolvable 1298 else: 1299 self.vm.reinitialize_if_initialized(node, instance) 1300 log.info("Resolved late annotation %r to %r", self.expr, self._type) 1301 1302 def to_variable(self, node): 1303 if self.resolved: 1304 return self._type.to_variable(node) 1305 else: 1306 return BaseValue.to_variable(self, node) 1307 1308 def instantiate(self, node, container=None): 1309 """Instantiate the pointed-to class, or record a placeholder instance.""" 1310 if self.resolved: 1311 return self._type.instantiate(node, container) 1312 else: 1313 instance = Instance(self, self.vm) 1314 self._unresolved_instances.add(instance) 1315 return instance.to_variable(node) 1316 1317 def get_special_attribute(self, node, name, valself): 1318 if name == "__getitem__" and not self.resolved: 1319 container = BaseValue.to_annotation_container(self) 1320 return container.get_special_attribute(node, name, valself) 1321 return self._type.get_special_attribute(node, name, valself) 1322 1323 def is_late_annotation(self): 1324 return True 1325 1326 1327class AnnotationClass(SimpleValue, mixin.HasSlots): 1328 """Base class of annotations that can be parameterized.""" 1329 1330 def __init__(self, name, vm): 1331 super().__init__(name, vm) 1332 mixin.HasSlots.init_mixin(self) 1333 self.set_slot("__getitem__", self.getitem_slot) 1334 1335 def getitem_slot(self, node, slice_var): 1336 """Custom __getitem__ implementation.""" 1337 slice_content = abstract_utils.maybe_extract_tuple(slice_var) 1338 inner, ellipses = self._build_inner(slice_content) 1339 value = self._build_value(node, tuple(inner), ellipses) 1340 return node, value.to_variable(node) 1341 1342 def _build_inner(self, slice_content): 1343 """Build the list of parameters. 1344 1345 Args: 1346 slice_content: The iterable of variables to extract parameters from. 1347 1348 Returns: 1349 A tuple of a list of parameters and a set of indices at which an ellipsis 1350 was replaced with Any. 1351 """ 1352 inner = [] 1353 ellipses = set() 1354 for var in slice_content: 1355 if len(var.bindings) > 1: 1356 self.vm.errorlog.ambiguous_annotation(self.vm.frames, var.data) 1357 inner.append(self.vm.convert.unsolvable) 1358 else: 1359 val = var.bindings[0].data 1360 if val is self.vm.convert.ellipsis: 1361 # Ellipses are allowed only in special cases, so turn them into Any 1362 # but record the indices so we can check if they're legal. 1363 ellipses.add(len(inner)) 1364 inner.append(self.vm.convert.unsolvable) 1365 else: 1366 inner.append(val) 1367 return inner, ellipses 1368 1369 def _build_value(self, node, inner, ellipses): 1370 raise NotImplementedError(self.__class__.__name__) 1371 1372 def __repr__(self): 1373 return "AnnotationClass(%s)" % self.name 1374 1375 1376class AnnotationContainer(AnnotationClass): 1377 """Implementation of X[...] for annotations.""" 1378 1379 def __init__(self, name, vm, base_cls): 1380 super().__init__(name, vm) 1381 self.base_cls = base_cls 1382 1383 def _sub_annotation( 1384 self, annot: BaseValue, subst: Mapping[str, BaseValue]) -> BaseValue: 1385 """Apply type parameter substitutions to an annotation.""" 1386 # This is very similar to annotations_util.sub_one_annotation, but a couple 1387 # differences make it more convenient to maintain two separate methods: 1388 # - subst here is a str->BaseValue mapping rather than str->Variable, and it 1389 # would be wasteful to create variables just to match sub_one_annotation's 1390 # expected input type. 1391 # - subst contains the type to be substituted in, not an instance of it. 1392 # Again, instantiating the type just to later get the type of the instance 1393 # is unnecessary extra work. 1394 if isinstance(annot, TypeParameter): 1395 if annot.full_name in subst: 1396 return subst[annot.full_name] 1397 else: 1398 return self.vm.convert.unsolvable 1399 elif isinstance(annot, mixin.NestedAnnotation): 1400 inner_types = [(key, self._sub_annotation(val, subst)) 1401 for key, val in annot.get_inner_types()] 1402 return annot.replace(inner_types) 1403 return annot 1404 1405 def _get_value_info(self, inner, ellipses, allowed_ellipses=frozenset()): 1406 """Get information about the container's inner values. 1407 1408 Args: 1409 inner: The list of parameters from _build_inner(). 1410 ellipses: The set of ellipsis indices from _build_inner(). 1411 allowed_ellipses: Optionally, a set of indices at which ellipses are 1412 allowed. If omitted, ellipses are assumed to be never allowed. 1413 1414 Returns: 1415 A tuple of the template, the parameters, and the container class. 1416 """ 1417 if self.base_cls.full_name == "typing.Protocol": 1418 return abstract_utils.build_generic_template(inner, self) + ( 1419 ParameterizedClass,) 1420 if isinstance(self.base_cls, TupleClass): 1421 template = tuple(range(self.base_cls.tuple_length)) 1422 elif isinstance(self.base_cls, CallableClass): 1423 template = tuple(range(self.base_cls.num_args)) + (abstract_utils.RET,) 1424 else: 1425 template = tuple(t.name for t in self.base_cls.template) 1426 self.vm.errorlog.invalid_ellipses( 1427 self.vm.frames, ellipses - allowed_ellipses, self.name) 1428 last_index = len(inner) - 1 1429 if last_index and last_index in ellipses and len(inner) > len(template): 1430 # Even if an ellipsis is not allowed at this position, strip it off so 1431 # that we report only one error for something like 'List[int, ...]' 1432 inner = inner[:-1] 1433 if isinstance(self.base_cls, ParameterizedClass): 1434 # We're dealing with a generic type alias, e.g.: 1435 # X = Dict[T, str] 1436 # def f(x: X[int]): ... 1437 # We construct `inner` using both the new inner values and the ones 1438 # already in X, to end up with a final result of: 1439 # template=(_K, _V) 1440 # inner=(int, str) 1441 new_inner = [] 1442 inner_idx = 0 1443 subst = {} 1444 # Note that we ignore any missing or extra values in inner for now; the 1445 # problem will be reported later by _validate_inner. 1446 for k in template: 1447 v = self.base_cls.formal_type_parameters[k] 1448 if v.formal: 1449 params = self.vm.annotations_util.get_type_parameters(v) 1450 for param in params: 1451 # If there are too few parameters, we ignore the problem for now; 1452 # it'll be reported when _build_value checks that the lengths of 1453 # template and inner match. 1454 if param.full_name not in subst and inner_idx < len(inner): 1455 subst[param.full_name] = inner[inner_idx] 1456 inner_idx += 1 1457 new_inner.append(self._sub_annotation(v, subst)) 1458 else: 1459 new_inner.append(v) 1460 inner = tuple(new_inner) 1461 if isinstance(self.base_cls, TupleClass): 1462 template += (abstract_utils.T,) 1463 inner += (self.vm.merge_values(inner),) 1464 elif isinstance(self.base_cls, CallableClass): 1465 template = template[:-1] + (abstract_utils.ARGS,) + template[-1:] 1466 args = inner[:-1] 1467 inner = args + (self.vm.merge_values(args),) + inner[-1:] 1468 abstract_class = type(self.base_cls) 1469 else: 1470 abstract_class = ParameterizedClass 1471 return template, inner, abstract_class 1472 1473 def _validate_inner(self, template, inner, raw_inner): 1474 """Check that the passed inner values are valid for the given template.""" 1475 if (isinstance(self.base_cls, ParameterizedClass) and 1476 not abstract_utils.is_generic_protocol(self.base_cls)): 1477 # For a generic type alias, we check that the number of typevars in the 1478 # alias matches the number of raw parameters provided. 1479 template_length = raw_template_length = len(set( 1480 self.vm.annotations_util.get_type_parameters(self.base_cls))) 1481 inner_length = raw_inner_length = len(raw_inner) 1482 base_cls = self.base_cls.base_cls 1483 else: 1484 # In all other cases, we check that the final template length and 1485 # parameter count match, after any adjustments like flattening the inner 1486 # argument list in a Callable. 1487 template_length = len(template) 1488 raw_template_length = len(self.base_cls.template) 1489 inner_length = len(inner) 1490 raw_inner_length = len(raw_inner) 1491 base_cls = self.base_cls 1492 if inner_length != template_length: 1493 if not template: 1494 self.vm.errorlog.not_indexable(self.vm.frames, base_cls.name, 1495 generic_warning=True) 1496 else: 1497 # Use the unprocessed values of `template` and `inner` so that the error 1498 # message matches what the user sees. 1499 name = "%s[%s]" % ( 1500 self.full_name, ", ".join(t.name for t in base_cls.template)) 1501 error = "Expected %d parameter(s), got %d" % ( 1502 raw_template_length, raw_inner_length) 1503 self.vm.errorlog.invalid_annotation(self.vm.frames, None, error, name) 1504 else: 1505 if len(inner) == 1: 1506 val, = inner 1507 # It's a common mistake to index a container class rather than an 1508 # instance (e.g., list[0]). 1509 # We only check the "int" case, since string literals are allowed for 1510 # late annotations. 1511 if isinstance(val, Instance) and val.cls == self.vm.convert.int_type: 1512 # Don't report this error again. 1513 inner = (self.vm.convert.unsolvable,) 1514 self.vm.errorlog.not_indexable(self.vm.frames, self.name) 1515 return inner 1516 1517 def _build_value(self, node, inner, ellipses): 1518 if self.base_cls.is_late_annotation(): 1519 # A parameterized LateAnnotation should be converted to another 1520 # LateAnnotation to delay evaluation until the first late annotation is 1521 # resolved. We don't want to create a ParameterizedClass immediately 1522 # because (1) ParameterizedClass expects its base_cls to be a 1523 # class_mixin.Class, and (2) we have to postpone error-checking anyway so 1524 # we might as well postpone the entire evaluation. 1525 printed_params = [] 1526 for i, param in enumerate(inner): 1527 if i in ellipses: 1528 printed_params.append("...") 1529 else: 1530 printed_params.append(pytd_utils.Print(param.get_instance_type(node))) 1531 expr = "%s[%s]" % (self.base_cls.expr, ", ".join(printed_params)) 1532 annot = LateAnnotation(expr, self.base_cls.stack, self.vm) 1533 self.vm.late_annotations[self.base_cls.expr].append(annot) 1534 return annot 1535 template, processed_inner, abstract_class = self._get_value_info( 1536 inner, ellipses) 1537 if isinstance(self.base_cls, ParameterizedClass): 1538 base_cls = self.base_cls.base_cls 1539 else: 1540 base_cls = self.base_cls 1541 if base_cls.full_name in ("typing.Generic", "typing.Protocol"): 1542 # Generic is unique in that parameterizing it defines a new template; 1543 # usually, the parameterized class inherits the base class's template. 1544 # Protocol[T, ...] is a shorthand for Protocol, Generic[T, ...]. 1545 template_params = [ 1546 param.with_module(base_cls.full_name) for param in processed_inner] 1547 else: 1548 template_params = None 1549 processed_inner = self._validate_inner(template, processed_inner, inner) 1550 params = {name: processed_inner[i] 1551 if i < len(processed_inner) else self.vm.convert.unsolvable 1552 for i, name in enumerate(template)} 1553 1554 # For user-defined generic types, check if its type parameter matches 1555 # its corresponding concrete type 1556 if isinstance(base_cls, InterpreterClass) and base_cls.template: 1557 for formal in base_cls.template: 1558 if (isinstance(formal, TypeParameter) and not formal.is_generic() and 1559 isinstance(params[formal.name], TypeParameter)): 1560 if formal.name != params[formal.name].name: 1561 self.vm.errorlog.not_supported_yet( 1562 self.vm.frames, 1563 "Renaming TypeVar `%s` with constraints or bound" % formal.name) 1564 else: 1565 root_node = self.vm.root_node 1566 actual = params[formal.name].instantiate(root_node) 1567 bad = self.vm.matcher(root_node).bad_matches(actual, formal) 1568 if bad: 1569 formal = self.vm.annotations_util.sub_one_annotation( 1570 root_node, formal, [{}]) 1571 self.vm.errorlog.bad_concrete_type( 1572 self.vm.frames, root_node, formal, actual, bad) 1573 return self.vm.convert.unsolvable 1574 1575 try: 1576 return abstract_class(base_cls, params, self.vm, template_params) 1577 except abstract_utils.GenericTypeError as e: 1578 self.vm.errorlog.invalid_annotation(self.vm.frames, e.annot, e.error) 1579 return self.vm.convert.unsolvable 1580 1581 1582class ConcreteValue(Instance, mixin.PythonConstant): 1583 """Abstract value with a concrete fallback.""" 1584 1585 def __init__(self, pyval, cls, vm): 1586 super().__init__(cls, vm) 1587 mixin.PythonConstant.init_mixin(self, pyval) 1588 1589 1590class LazyConcreteDict(SimpleValue, mixin.PythonConstant, mixin.LazyMembers): 1591 """Dictionary with lazy values.""" 1592 1593 def __init__(self, name, member_map, vm): 1594 super().__init__(name, vm) 1595 mixin.PythonConstant.init_mixin(self, self.members) 1596 mixin.LazyMembers.init_mixin(self, member_map) 1597 1598 def _convert_member(self, member, subst=None): 1599 return self.vm.convert.constant_to_var(member) 1600 1601 def is_empty(self): 1602 return not bool(self._member_map) 1603 1604 1605class Union(BaseValue, mixin.NestedAnnotation, mixin.HasSlots): 1606 """A list of types. 1607 1608 Used for parameter matching. 1609 1610 Attributes: 1611 options: Iterable of instances of BaseValue. 1612 """ 1613 1614 def __init__(self, options, vm): 1615 super().__init__("Union", vm) 1616 assert options 1617 self.options = list(options) 1618 # TODO(rechen): Don't allow a mix of formal and non-formal types 1619 self.formal = any(t.formal for t in self.options) 1620 mixin.NestedAnnotation.init_mixin(self) 1621 mixin.HasSlots.init_mixin(self) 1622 self.set_slot("__getitem__", self.getitem_slot) 1623 1624 def __repr__(self): 1625 return "%s[%s]" % (self.name, ", ".join(repr(o) for o in self.options)) 1626 1627 def __eq__(self, other): 1628 if isinstance(other, type(self)): 1629 return self.options == other.options 1630 return NotImplemented 1631 1632 def __ne__(self, other): 1633 return not self == other 1634 1635 def __hash__(self): 1636 return hash(tuple(self.options)) 1637 1638 def _unique_parameters(self): 1639 return [o.to_variable(self.vm.root_node) for o in self.options] 1640 1641 def _get_type_params(self): 1642 params = self.vm.annotations_util.get_type_parameters(self) 1643 params = [x.full_name for x in params] 1644 return utils.unique_list(params) 1645 1646 def getitem_slot(self, node, slice_var): 1647 """Custom __getitem__ implementation.""" 1648 slice_content = abstract_utils.maybe_extract_tuple(slice_var) 1649 params = self._get_type_params() 1650 # Check that we are instantiating all the unbound type parameters 1651 if len(params) != len(slice_content): 1652 details = ("Union has %d type parameters but was instantiated with %d" % 1653 (len(params), len(slice_content))) 1654 self.vm.errorlog.invalid_annotation( 1655 self.vm.frames, self, details=details) 1656 return node, self.vm.new_unsolvable(node) 1657 concrete = [] 1658 for var in slice_content: 1659 value = var.data[0] 1660 if value.formal: 1661 concrete.append(value.to_variable(node)) 1662 else: 1663 concrete.append(value.instantiate(node)) 1664 substs = [dict(zip(params, concrete))] 1665 new = self.vm.annotations_util.sub_one_annotation(node, self, substs) 1666 return node, new.to_variable(node) 1667 1668 def instantiate(self, node, container=None): 1669 var = self.vm.program.NewVariable() 1670 for option in self.options: 1671 var.PasteVariable(option.instantiate(node, container), node) 1672 return var 1673 1674 def get_class(self): 1675 classes = {o.get_class() for o in self.options} 1676 if len(classes) > 1: 1677 return self.vm.convert.unsolvable 1678 else: 1679 return classes.pop() 1680 1681 def call(self, node, func, args, alias_map=None): 1682 var = self.vm.program.NewVariable(self.options, [], node) 1683 return self.vm.call_function(node, var, args) 1684 1685 def get_formal_type_parameter(self, t): 1686 new_options = [option.get_formal_type_parameter(t) 1687 for option in self.options] 1688 return Union(new_options, self.vm) 1689 1690 def get_inner_types(self): 1691 return enumerate(self.options) 1692 1693 def update_inner_type(self, key, typ): 1694 self.options[key] = typ 1695 1696 def replace(self, inner_types): 1697 return self.__class__((v for _, v in sorted(inner_types)), self.vm) 1698 1699 1700class Function(SimpleValue): 1701 """Base class for function objects (NativeFunction, InterpreterFunction). 1702 1703 Attributes: 1704 name: Function name. Might just be something like "<lambda>". 1705 vm: TypegraphVirtualMachine instance. 1706 """ 1707 1708 def __init__(self, name, vm): 1709 super().__init__(name, vm) 1710 self.cls = FunctionPyTDClass(self, vm) 1711 self.is_attribute_of_class = False 1712 self.is_classmethod = False 1713 self.is_abstract = False 1714 self.members["func_name"] = self.vm.convert.build_string( 1715 self.vm.root_node, name) 1716 1717 def property_get(self, callself, is_class=False): 1718 if self.name == "__new__" or not callself or is_class: 1719 return self 1720 self.is_attribute_of_class = True 1721 # We'd like to cache this, but we can't. "callself" contains Variables 1722 # that would be tied into a BoundFunction instance. However, those 1723 # Variables aren't necessarily visible from other parts of the CFG binding 1724 # this function. See test_duplicate_getproperty() in tests/test_flow.py. 1725 return self.bound_class(callself, self) 1726 1727 def _get_cell_variable_name(self, var): 1728 """Get the python variable name of a pytype Variable.""" 1729 f = self.vm.frame 1730 if not f: 1731 # Should not happen but does in some contrived test cases. 1732 return None 1733 for name, v in zip(f.f_code.co_freevars, f.cells): 1734 if v == var: 1735 return name 1736 return None 1737 1738 def match_args(self, node, args, alias_map=None, match_all_views=False): 1739 """Check whether the given arguments can match the function signature.""" 1740 for a in args.posargs: 1741 if not a.bindings: 1742 # The only way to get an unbound variable here is to reference a closure 1743 # cellvar before it is assigned to in the outer scope. 1744 name = self._get_cell_variable_name(a) 1745 assert name is not None, "Closure variable lookup failed." 1746 raise function.UndefinedParameterError(name) 1747 error = None 1748 matched = [] 1749 arg_variables = args.get_variables() 1750 views = abstract_utils.get_views(arg_variables, node) 1751 skip_future = None 1752 while True: 1753 try: 1754 view = views.send(skip_future) 1755 except StopIteration: 1756 break 1757 log.debug("args in view: %r", [(a.bindings and view[a].data) 1758 for a in args.posargs]) 1759 try: 1760 match = self._match_view(node, args, view, alias_map) 1761 except function.FailedFunctionCall as e: 1762 if e > error and node.HasCombination(list(view.values())): 1763 # Add the name of the caller if possible. 1764 if hasattr(self, "parent"): 1765 e.name = "%s.%s" % (self.parent.name, e.name) 1766 error = e 1767 skip_future = True 1768 else: 1769 # This error was ignored, but future ones with the same accessed 1770 # subset may need to be recorded, so we can't skip them. 1771 skip_future = False 1772 if match_all_views: 1773 raise e 1774 else: 1775 matched.append(match) 1776 skip_future = True 1777 if not matched and error: 1778 raise error # pylint: disable=raising-bad-type 1779 return matched 1780 1781 def _match_view(self, node, args, view, alias_map): 1782 raise NotImplementedError(self.__class__.__name__) 1783 1784 def __repr__(self): 1785 return self.full_name + "(...)" 1786 1787 def _extract_defaults(self, defaults_var): 1788 """Extracts defaults from a Variable, used by set_function_defaults. 1789 1790 Args: 1791 defaults_var: Variable containing potential default values. 1792 1793 Returns: 1794 A tuple of default values, if one could be extracted, or None otherwise. 1795 """ 1796 # Case 1: All given data are tuple constants. Use the longest one. 1797 if all(isinstance(d, Tuple) for d in defaults_var.data): 1798 return max((d.pyval for d in defaults_var.data), key=len) 1799 else: 1800 # Case 2: Data are entirely Tuple Instances, Unknown or Unsolvable. Make 1801 # all parameters except self/cls optional. 1802 # Case 3: Data is anything else. Same as Case 2, but emit a warning. 1803 if not (all(isinstance(d, (Instance, Unknown, Unsolvable)) 1804 for d in defaults_var.data) and 1805 all(d.full_name == "builtins.tuple" 1806 for d in defaults_var.data if isinstance(d, Instance))): 1807 self.vm.errorlog.bad_function_defaults(self.vm.frames, self.name) 1808 # The ambiguous case is handled by the subclass. 1809 return None 1810 1811 def set_function_defaults(self, node, defaults_var): 1812 raise NotImplementedError(self.__class__.__name__) 1813 1814 1815class ClassMethod(BaseValue): 1816 """Implements @classmethod methods in pyi.""" 1817 1818 def __init__(self, name, method, callself, vm): 1819 super().__init__(name, vm) 1820 self.method = method 1821 self.method.is_attribute_of_class = True 1822 # Rename to callcls to make clear that callself is the cls parameter. 1823 self._callcls = callself 1824 self.signatures = self.method.signatures 1825 1826 def call(self, node, func, args, alias_map=None): 1827 return self.method.call( 1828 node, func, args.replace(posargs=(self._callcls,) + args.posargs)) 1829 1830 def get_class(self): 1831 return self.vm.convert.function_type 1832 1833 def to_bound_function(self): 1834 return BoundPyTDFunction(self._callcls, self.method) 1835 1836 1837class StaticMethod(BaseValue): 1838 """Implements @staticmethod methods in pyi.""" 1839 1840 def __init__(self, name, method, _, vm): 1841 super().__init__(name, vm) 1842 self.method = method 1843 self.signatures = self.method.signatures 1844 1845 def call(self, *args, **kwargs): 1846 return self.method.call(*args, **kwargs) 1847 1848 def get_class(self): 1849 return self.vm.convert.function_type 1850 1851 1852class Property(BaseValue): 1853 """Implements @property methods in pyi. 1854 1855 If a getter's return type depends on the type of the class, it needs to be 1856 resolved as a function, not as a constant. 1857 """ 1858 1859 def __init__(self, name, method, callself, vm): 1860 super().__init__(name, vm) 1861 self.method = method 1862 self._callself = callself 1863 self.signatures = self.method.signatures 1864 1865 def call(self, node, func, args, alias_map=None): 1866 func = func or self.to_binding(node) 1867 args = args or function.Args(posargs=(self._callself,)) 1868 return self.method.call(node, func, args.replace(posargs=(self._callself,))) 1869 1870 def get_class(self): 1871 return self.vm.convert.function_type 1872 1873 1874class PyTDFunction(Function): 1875 """A PyTD function (name + list of signatures). 1876 1877 This represents (potentially overloaded) functions. 1878 """ 1879 1880 @classmethod 1881 def make(cls, name, vm, module, pyval=None, pyval_name=None): 1882 """Create a PyTDFunction. 1883 1884 Args: 1885 name: The function name. 1886 vm: The VM. 1887 module: The module that the function is in. 1888 pyval: Optionally, the pytd.Function object to use. Otherwise, it is 1889 fetched from the loader. 1890 pyval_name: Optionally, the name of the pytd.Function object to look up, 1891 if it is different from the function name. 1892 1893 Returns: 1894 A new PyTDFunction. 1895 """ 1896 assert not pyval or not pyval_name # there's never a reason to pass both 1897 if not pyval: 1898 pyval_name = module + "." + (pyval_name or name) 1899 if module not in ("builtins", "typing"): 1900 pyval = vm.loader.import_name(module).Lookup(pyval_name) 1901 else: 1902 pyval = vm.lookup_builtin(pyval_name) 1903 if isinstance(pyval, pytd.Alias) and isinstance(pyval.type, pytd.Function): 1904 pyval = pyval.type 1905 f = vm.convert.constant_to_value(pyval, {}, vm.root_node) 1906 self = cls(name, f.signatures, pyval.kind, vm) 1907 self.module = module 1908 return self 1909 1910 def __init__(self, name, signatures, kind, vm): 1911 super().__init__(name, vm) 1912 assert signatures 1913 self.kind = kind 1914 self.bound_class = BoundPyTDFunction 1915 self.signatures = signatures 1916 self._signature_cache = {} 1917 self._return_types = {sig.pytd_sig.return_type for sig in signatures} 1918 for sig in signatures: 1919 for param in sig.pytd_sig.params: 1920 if param.mutated_type is not None: 1921 self._has_mutable = True 1922 break 1923 else: 1924 self._has_mutable = False 1925 for sig in signatures: 1926 sig.function = self 1927 sig.name = self.name 1928 1929 def property_get(self, callself, is_class=False): 1930 if self.kind == pytd.MethodTypes.STATICMETHOD: 1931 if is_class: 1932 # Binding the function to None rather than not binding it tells 1933 # output.py to infer the type as a Callable rather than reproducing the 1934 # signature, including the @staticmethod decorator, which is 1935 # undesirable for module-level aliases. 1936 callself = None 1937 return StaticMethod(self.name, self, callself, self.vm) 1938 elif self.kind == pytd.MethodTypes.CLASSMETHOD: 1939 if not is_class: 1940 callself = abstract_utils.get_atomic_value( 1941 callself, default=self.vm.convert.unsolvable) 1942 if isinstance(callself, TypeParameterInstance): 1943 callself = abstract_utils.get_atomic_value( 1944 callself.instance.get_instance_type_parameter(callself.name), 1945 default=self.vm.convert.unsolvable) 1946 # callself is the instance, and we want to bind to its class. 1947 callself = callself.get_class().to_variable(self.vm.root_node) 1948 return ClassMethod(self.name, self, callself, self.vm) 1949 elif self.kind == pytd.MethodTypes.PROPERTY and not is_class: 1950 return Property(self.name, self, callself, self.vm) 1951 else: 1952 return super().property_get(callself, is_class) 1953 1954 def argcount(self, _): 1955 return min(sig.signature.mandatory_param_count() for sig in self.signatures) 1956 1957 def _log_args(self, arg_values_list, level=0, logged=None): 1958 """Log the argument values.""" 1959 if log.isEnabledFor(logging.DEBUG): 1960 if logged is None: 1961 logged = set() 1962 for i, arg_values in enumerate(arg_values_list): 1963 arg_values = list(arg_values) 1964 if level: 1965 if arg_values and any(v.data not in logged for v in arg_values): 1966 log.debug("%s%s:", " " * level, arg_values[0].variable.id) 1967 else: 1968 log.debug("Arg %d", i) 1969 for value in arg_values: 1970 if value.data not in logged: 1971 log.debug("%s%s [var %d]", " " * (level + 1), value.data, 1972 value.variable.id) 1973 self._log_args(value.data.unique_parameter_values(), level + 2, 1974 logged | {value.data}) 1975 1976 def call(self, node, func, args, alias_map=None): 1977 # TODO(b/159052609): We should be passing function signatures to simplify. 1978 if len(self.signatures) == 1: 1979 args = args.simplify(node, self.vm, self.signatures[0].signature) 1980 else: 1981 args = args.simplify(node, self.vm) 1982 self._log_args(arg.bindings for arg in args.posargs) 1983 ret_map = {} 1984 retvar = self.vm.program.NewVariable() 1985 all_mutations = {} 1986 # The following line may raise function.FailedFunctionCall 1987 possible_calls = self.match_args(node, args, alias_map) 1988 # It's possible for the substitution dictionary computed for a particular 1989 # view of 'args' to contain references to variables not in the view because 1990 # of optimizations that copy bindings directly into subst without going 1991 # through the normal matching process. Thus, we create a combined view that 1992 # is guaranteed to contain an entry for every variable in every view for use 1993 # by the match_var_against_type() call in 'compatible_with' below. 1994 combined_view = {} 1995 for view, signatures in possible_calls: 1996 if len(signatures) > 1: 1997 ret = self._call_with_signatures(node, func, args, view, signatures) 1998 else: 1999 (sig, arg_dict, subst), = signatures 2000 ret = sig.call_with_args( 2001 node, func, arg_dict, subst, ret_map, alias_map) 2002 node, result, mutations = ret 2003 retvar.PasteVariable(result, node) 2004 for mutation in mutations: 2005 # This may overwrite a previous view, which is fine: we just want any 2006 # valid view to pass to match_var_against_type() later. 2007 all_mutations[mutation] = view 2008 combined_view.update(view) 2009 2010 # Don't check container types if the function has multiple bindings. 2011 # This is a hack to prevent false positives when we call a method on a 2012 # variable with multiple bindings, since we don't always filter rigorously 2013 # enough in get_views. 2014 # See tests/test_annotations:test_list for an example that would break 2015 # if we removed the len(bindings) check. 2016 if all_mutations and len(func.variable.Bindings(node)) == 1: 2017 # Raise an error if: 2018 # - An annotation has a type param that is not ambigious or empty 2019 # - The mutation adds a type that is not ambiguous or empty 2020 def should_check(value): 2021 return not value.isinstance_AMBIGUOUS_OR_EMPTY() and value.cls 2022 2023 def compatible_with(new, existing, view): 2024 """Check whether a new type can be added to a container.""" 2025 new_key = view[new].data.get_type_key() 2026 for data in existing: 2027 k = (new_key, data.get_type_key()) 2028 if k not in compatible_with_cache: 2029 # This caching lets us skip duplicate matching work. Very 2030 # unfortunately, it is also needed for correctness because 2031 # cfg_utils.deep_variable_product() ignores bindings to values with 2032 # duplicate type keys when generating views. 2033 compatible_with_cache[k] = self.vm.matcher( 2034 node).match_var_against_type(new, data.cls, {}, view) 2035 if compatible_with_cache[k] is not None: 2036 return True 2037 return False 2038 2039 compatible_with_cache = {} 2040 filtered_mutations = [] 2041 errors = collections.defaultdict(dict) 2042 2043 for (obj, name, values), view in all_mutations.items(): 2044 if obj.from_annotation: 2045 params = obj.get_instance_type_parameter(name) 2046 ps = {v for v in params.data if should_check(v)} 2047 if ps: 2048 filtered_values = self.vm.program.NewVariable() 2049 # check if the container type is being broadened. 2050 new = [] 2051 for b in values.bindings: 2052 if not should_check(b.data) or b.data in ps: 2053 filtered_values.PasteBinding(b) 2054 continue 2055 new_view = {**combined_view, **view, values: b} 2056 if not compatible_with(values, ps, new_view): 2057 if not node.HasCombination([b]): 2058 # Since HasCombination is expensive, we don't use it to 2059 # pre-filter bindings, but once we think we have an error, we 2060 # should double-check that the binding is actually visible. We 2061 # also drop non-visible bindings from filtered_values. 2062 continue 2063 filtered_values.PasteBinding(b) 2064 new.append(b.data) 2065 # By updating filtered_mutations only when ps is non-empty, we 2066 # filter out mutations to parameters with type Any. 2067 filtered_mutations.append((obj, name, filtered_values)) 2068 if new: 2069 formal = name.split(".")[-1] 2070 errors[obj][formal] = (params, values, obj.from_annotation) 2071 else: 2072 filtered_mutations.append((obj, name, values)) 2073 2074 all_mutations = filtered_mutations 2075 2076 for obj, errs in errors.items(): 2077 names = {name for _, _, name in errs.values()} 2078 name = list(names)[0] if len(names) == 1 else None 2079 self.vm.errorlog.container_type_mismatch( 2080 self.vm.frames, obj, errs, name) 2081 2082 node = abstract_utils.apply_mutations(node, all_mutations.__iter__) 2083 return node, retvar 2084 2085 def _get_mutation_to_unknown(self, node, values): 2086 """Mutation for making all type parameters in a list of instances "unknown". 2087 2088 This is used if we call a function that has mutable parameters and 2089 multiple signatures with unknown parameters. 2090 2091 Args: 2092 node: The current CFG node. 2093 values: A list of instances of BaseValue. 2094 2095 Returns: 2096 A list of function.Mutation instances. 2097 """ 2098 mutations = [] 2099 for v in values: 2100 if isinstance(v, SimpleValue): 2101 for name in v.instance_type_parameters: 2102 mutations.append( 2103 function.Mutation(v, name, self.vm.convert.create_new_unknown( 2104 node, action="type_param_" + name))) 2105 return mutations 2106 2107 def _can_match_multiple(self, args, view): 2108 # If we're calling an overloaded pytd function with an unknown as a 2109 # parameter, we can't tell whether it matched or not. Hence, if multiple 2110 # signatures are possible matches, we don't know which got called. Check 2111 # if this is the case. 2112 if len(self.signatures) <= 1: 2113 return False 2114 if any(isinstance(view[arg].data, AMBIGUOUS_OR_EMPTY) 2115 for arg in args.get_variables()): 2116 return True 2117 for arg in (args.starargs, args.starstarargs): 2118 # An opaque *args or **kwargs behaves like an unknown. 2119 if arg and not isinstance(arg, mixin.PythonConstant): 2120 return True 2121 return False 2122 2123 def _match_view(self, node, args, view, alias_map=None): 2124 if self._can_match_multiple(args, view): 2125 signatures = tuple(self._yield_matching_signatures( 2126 node, args, view, alias_map)) 2127 else: 2128 # We take the first signature that matches, and ignore all after it. 2129 # This is because in the pytds for the standard library, the last 2130 # signature(s) is/are fallback(s) - e.g. list is defined by 2131 # def __init__(self: x: list) 2132 # def __init__(self, x: iterable) 2133 # def __init__(self, x: generator) 2134 # def __init__(self, x: object) 2135 # with the last signature only being used if none of the others match. 2136 sig = next(self._yield_matching_signatures(node, args, view, alias_map)) 2137 signatures = (sig,) 2138 return (view, signatures) 2139 2140 def _call_with_signatures(self, node, func, args, view, signatures): 2141 """Perform a function call that involves multiple signatures.""" 2142 ret_type = self._combine_multiple_returns(signatures) 2143 if self.vm.options.protocols and isinstance(ret_type, pytd.AnythingType): 2144 # We can infer a more specific type. 2145 log.debug("Creating unknown return") 2146 result = self.vm.convert.create_new_unknown( 2147 node, action="pytd_call") 2148 else: 2149 log.debug("Unknown args. But return is %s", pytd_utils.Print(ret_type)) 2150 result = self.vm.convert.constant_to_var( 2151 abstract_utils.AsReturnValue(ret_type), {}, node) 2152 for i, arg in enumerate(args.posargs): 2153 if isinstance(view[arg].data, Unknown): 2154 for sig, _, _ in signatures: 2155 if (len(sig.param_types) > i and 2156 isinstance(sig.param_types[i], TypeParameter)): 2157 # Change this parameter from unknown to unsolvable to prevent the 2158 # unknown from being solved to a type in another signature. For 2159 # instance, with the following definitions: 2160 # def f(x: T) -> T 2161 # def f(x: int) -> T 2162 # the type of x should be Any, not int. 2163 view[arg] = arg.AddBinding(self.vm.convert.unsolvable, [], node) 2164 break 2165 if self._has_mutable: 2166 # TODO(b/159055015): We only need to whack the type params that appear in 2167 # a mutable parameter. 2168 mutations = self._get_mutation_to_unknown( 2169 node, (view[p].data for p in itertools.chain( 2170 args.posargs, args.namedargs.values()))) 2171 else: 2172 mutations = [] 2173 self.vm.trace_call(node, func, tuple(sig[0] for sig in signatures), 2174 [view[arg] for arg in args.posargs], 2175 {name: view[arg] 2176 for name, arg in args.namedargs.items()}, 2177 result) 2178 return node, result, mutations 2179 2180 def _combine_multiple_returns(self, signatures): 2181 """Combines multiple return types. 2182 2183 Args: 2184 signatures: The candidate signatures. 2185 2186 Returns: 2187 The combined return type. 2188 """ 2189 options = [] 2190 for sig, _, _ in signatures: 2191 t = sig.pytd_sig.return_type 2192 params = pytd_utils.GetTypeParameters(t) 2193 if params: 2194 replacement = {} 2195 for param_type in params: 2196 replacement[param_type] = pytd.AnythingType() 2197 replace_visitor = visitors.ReplaceTypeParameters(replacement) 2198 t = t.Visit(replace_visitor) 2199 options.append(t) 2200 if len(set(options)) == 1: 2201 return options[0] 2202 # Optimizing and then removing unions allows us to preserve as much 2203 # precision as possible while avoiding false positives. 2204 ret_type = optimize.Optimize(pytd_utils.JoinTypes(options)) 2205 return ret_type.Visit(visitors.ReplaceUnionsWithAny()) 2206 2207 def _yield_matching_signatures(self, node, args, view, alias_map): 2208 """Try, in order, all pytd signatures, yielding matches.""" 2209 error = None 2210 matched = False 2211 # Once a constant has matched a literal type, it should no longer be able to 2212 # match non-literal types. For example, with: 2213 # @overload 2214 # def f(x: Literal['r']): ... 2215 # @overload 2216 # def f(x: str): ... 2217 # f('r') should match only the first signature. 2218 literal_matches = set() 2219 for sig in self.signatures: 2220 if any(not abstract_utils.is_literal(sig.signature.annotations.get(name)) 2221 for name in literal_matches): 2222 continue 2223 try: 2224 arg_dict, subst = sig.substitute_formal_args( 2225 node, args, view, alias_map) 2226 except function.FailedFunctionCall as e: 2227 if e > error: 2228 error = e 2229 else: 2230 matched = True 2231 for name, binding in arg_dict.items(): 2232 if (isinstance(binding.data, mixin.PythonConstant) and 2233 abstract_utils.is_literal(sig.signature.annotations.get(name))): 2234 literal_matches.add(name) 2235 yield sig, arg_dict, subst 2236 if not matched: 2237 raise error # pylint: disable=raising-bad-type 2238 2239 def set_function_defaults(self, unused_node, defaults_var): 2240 """Attempts to set default arguments for a function's signatures. 2241 2242 If defaults_var is not an unambiguous tuple (i.e. one that can be processed 2243 by abstract_utils.get_atomic_python_constant), every argument is made 2244 optional and a warning is issued. This function emulates __defaults__. 2245 2246 If this function is part of a class (or has a parent), that parent is 2247 updated so the change is stored. 2248 2249 Args: 2250 unused_node: the node that defaults are being set at. Not used here. 2251 defaults_var: a Variable with a single binding to a tuple of default 2252 values. 2253 """ 2254 defaults = self._extract_defaults(defaults_var) 2255 new_sigs = [] 2256 for sig in self.signatures: 2257 if defaults: 2258 new_sigs.append(sig.set_defaults(defaults)) 2259 else: 2260 d = sig.param_types 2261 # If we have a parent, we have a "self" or "cls" parameter. Do NOT make 2262 # that one optional! 2263 if hasattr(self, "parent"): 2264 d = d[1:] 2265 new_sigs.append(sig.set_defaults(d)) 2266 self.signatures = new_sigs 2267 # Update our parent's AST too, if we have a parent. 2268 # 'parent' is set by PyTDClass._convert_member 2269 if hasattr(self, "parent"): 2270 self.parent._member_map[self.name] = self.generate_ast() # pylint: disable=protected-access 2271 2272 def generate_ast(self): 2273 return pytd.Function( 2274 name=self.name, 2275 signatures=tuple(s.pytd_sig for s in self.signatures), 2276 kind=self.kind, 2277 flags=pytd.MethodFlags.abstract_flag(self.is_abstract)) 2278 2279 2280class ParameterizedClass(BaseValue, class_mixin.Class, mixin.NestedAnnotation): 2281 """A class that contains additional parameters. 2282 2283 E.g. a container. 2284 2285 Attributes: 2286 cls: A PyTDClass representing the base type. 2287 formal_type_parameters: An iterable of BaseValue, one for each type 2288 parameter. 2289 """ 2290 2291 @classmethod 2292 def get_generic_instance_type(cls, base_cls): 2293 """This is used to annotate the `self` in a class.""" 2294 assert base_cls.template 2295 formal_type_parameters = {} 2296 for item in base_cls.template: 2297 formal_type_parameters[item.name] = item 2298 return cls(base_cls, formal_type_parameters, base_cls.vm) 2299 2300 def __init__(self, base_cls, formal_type_parameters, vm, template=None): 2301 # A ParameterizedClass is created by converting a pytd.GenericType, whose 2302 # base type is restricted to NamedType and ClassType. 2303 assert isinstance(base_cls, (PyTDClass, InterpreterClass)) 2304 self.base_cls = base_cls 2305 super().__init__(base_cls.name, vm) 2306 self.module = base_cls.module 2307 # Lazily loaded to handle recursive types. 2308 # See the formal_type_parameters() property. 2309 self._formal_type_parameters = formal_type_parameters 2310 self._formal_type_parameters_loaded = False 2311 self._hash = None # memoized due to expensive computation 2312 self.official_name = self.base_cls.official_name 2313 if template is None: 2314 self._template = self.base_cls.template 2315 else: 2316 # The ability to create a new template different from the base class's is 2317 # needed for typing.Generic. 2318 self._template = template 2319 self.slots = self.base_cls.slots 2320 self.is_dynamic = self.base_cls.is_dynamic 2321 class_mixin.Class.init_mixin(self, base_cls.cls) 2322 mixin.NestedAnnotation.init_mixin(self) 2323 self.type_param_check() 2324 2325 def __repr__(self): 2326 return "ParameterizedClass(cls=%r params=%s)" % ( 2327 self.base_cls, 2328 self.formal_type_parameters) 2329 2330 def type_param_check(self): 2331 """Throw exception for invalid type parameters.""" 2332 # It will cause infinite recursion if `formal_type_parameters` is 2333 # `LazyFormalTypeParameters` 2334 if not isinstance(self._formal_type_parameters, 2335 abstract_utils.LazyFormalTypeParameters): 2336 tparams = datatypes.AliasingMonitorDict() 2337 abstract_utils.parse_formal_type_parameters(self, None, tparams) 2338 2339 def get_formal_type_parameters(self): 2340 return {abstract_utils.full_type_name(self, k): v 2341 for k, v in self.formal_type_parameters.items()} 2342 2343 def __eq__(self, other): 2344 if isinstance(other, type(self)): 2345 return self.base_cls == other.base_cls and ( 2346 self.formal_type_parameters == other.formal_type_parameters) 2347 return NotImplemented 2348 2349 def __ne__(self, other): 2350 return not self == other 2351 2352 def __hash__(self): 2353 if self._hash is None: 2354 if isinstance(self._formal_type_parameters, 2355 abstract_utils.LazyFormalTypeParameters): 2356 items = tuple(self._raw_formal_type_parameters()) 2357 else: 2358 # Use the names of the parameter values to approximate a hash, to avoid 2359 # infinite recursion on recursive type annotations. 2360 items = tuple((name, val.full_name) 2361 for name, val in self.formal_type_parameters.items()) 2362 self._hash = hash((self.base_cls, items)) 2363 return self._hash 2364 2365 def __contains__(self, name): 2366 return name in self.base_cls 2367 2368 def _raw_formal_type_parameters(self): 2369 assert isinstance(self._formal_type_parameters, 2370 abstract_utils.LazyFormalTypeParameters) 2371 template, parameters, _ = self._formal_type_parameters 2372 for i, name in enumerate(template): 2373 # TODO(rechen): A missing parameter should be an error. 2374 yield name, parameters[i] if i < len(parameters) else None 2375 2376 def get_own_attributes(self): 2377 return self.base_cls.get_own_attributes() 2378 2379 def get_own_abstract_methods(self): 2380 return self.base_cls.get_own_abstract_methods() 2381 2382 @property 2383 def members(self): 2384 return self.base_cls.members 2385 2386 @property 2387 def formal(self): 2388 # We can't compute self.formal in __init__ because doing so would force 2389 # evaluation of our type parameters during initialization, possibly 2390 # leading to an infinite loop. 2391 return any(t.formal for t in self.formal_type_parameters.values()) 2392 2393 @property 2394 def formal_type_parameters(self): 2395 self._load_formal_type_parameters() 2396 return self._formal_type_parameters 2397 2398 def _load_formal_type_parameters(self): 2399 if self._formal_type_parameters_loaded: 2400 return 2401 if isinstance(self._formal_type_parameters, 2402 abstract_utils.LazyFormalTypeParameters): 2403 formal_type_parameters = {} 2404 for name, param in self._raw_formal_type_parameters(): 2405 if param is None: 2406 formal_type_parameters[name] = self.vm.convert.unsolvable 2407 else: 2408 formal_type_parameters[name] = self.vm.convert.constant_to_value( 2409 param, self._formal_type_parameters.subst, self.vm.root_node) 2410 self._formal_type_parameters = formal_type_parameters 2411 # Hack: we'd like to evaluate annotations at the currently active node so 2412 # that imports, etc., are visible. The last created node is usually the 2413 # active one. 2414 self._formal_type_parameters = ( 2415 self.vm.annotations_util.convert_class_annotations( 2416 self.vm.program.cfg_nodes[-1], self._formal_type_parameters)) 2417 self._formal_type_parameters_loaded = True 2418 2419 def compute_mro(self): 2420 return (self,) + self.base_cls.mro[1:] 2421 2422 def instantiate(self, node, container=None): 2423 if self.full_name == "builtins.type": 2424 # deformalize removes TypeVars. 2425 instance = self.vm.annotations_util.deformalize( 2426 self.formal_type_parameters[abstract_utils.T]) 2427 return instance.to_variable(node) 2428 elif self.full_name == "typing.ClassVar": 2429 return self.formal_type_parameters[abstract_utils.T].instantiate( 2430 node, container) 2431 elif self.vm.frame and self.vm.frame.current_opcode: 2432 return self._new_instance(container).to_variable(node) 2433 else: 2434 return super().instantiate(node, container) 2435 2436 def get_class(self): 2437 return self.base_cls.get_class() 2438 2439 def set_class(self, node, var): 2440 self.base_cls.set_class(node, var) 2441 2442 def _is_callable(self): 2443 if not isinstance(self.base_cls, (InterpreterClass, PyTDClass)): 2444 # We don't know how to instantiate this base_cls. 2445 return False 2446 if self.from_annotation: 2447 # A user-provided annotation is always instantiable. 2448 return True 2449 # Otherwise, non-abstract classes are instantiable. The exception is 2450 # typing classes; for example, 2451 # from typing import List 2452 # print(List[str]()) 2453 # produces 'TypeError: Type List cannot be instantiated; use list() instead' 2454 # at runtime. We also disallow the builtins module because pytype represents 2455 # concrete typing classes like List with their builtins equivalents. 2456 return not self.is_abstract and self.module not in ("builtins", "typing") 2457 2458 def call(self, node, func, args, alias_map=None): 2459 if not self._is_callable(): 2460 raise function.NotCallable(self) 2461 else: 2462 return class_mixin.Class.call(self, node, func, args) 2463 2464 def get_formal_type_parameter(self, t): 2465 return self.formal_type_parameters.get(t, self.vm.convert.unsolvable) 2466 2467 def get_inner_types(self): 2468 return self.formal_type_parameters.items() 2469 2470 def update_inner_type(self, key, typ): 2471 self.formal_type_parameters[key] = typ 2472 2473 def replace(self, inner_types): 2474 inner_types = dict(inner_types) 2475 if isinstance(self, LiteralClass): 2476 if inner_types == self.formal_type_parameters: 2477 # If the type hasn't changed, we can return a copy of this class. 2478 return LiteralClass(self._instance, self.vm, self.template) 2479 # Otherwise, we can't create a LiteralClass because we don't have a 2480 # concrete value. 2481 typ = ParameterizedClass 2482 else: 2483 typ = self.__class__ 2484 return typ(self.base_cls, inner_types, self.vm, self.template) 2485 2486 2487class TupleClass(ParameterizedClass, mixin.HasSlots): 2488 """The class of a heterogeneous tuple. 2489 2490 The formal_type_parameters attribute stores the types of the individual tuple 2491 elements under their indices and the overall element type under "T". So for 2492 Tuple[str, int] 2493 formal_type_parameters is 2494 {0: str, 1: int, T: str or int}. 2495 Note that we can't store the individual types as a mixin.PythonConstant as we 2496 do for Tuple, since we can't evaluate type parameters during initialization. 2497 """ 2498 2499 def __init__(self, base_cls, formal_type_parameters, vm, template=None): 2500 super().__init__(base_cls, formal_type_parameters, vm, template) 2501 mixin.HasSlots.init_mixin(self) 2502 self.set_slot("__getitem__", self.getitem_slot) 2503 if isinstance(self._formal_type_parameters, 2504 abstract_utils.LazyFormalTypeParameters): 2505 num_parameters = len(self._formal_type_parameters.template) 2506 else: 2507 num_parameters = len(self._formal_type_parameters) 2508 # We subtract one to account for "T". 2509 self.tuple_length = num_parameters - 1 2510 self._instance = None 2511 self.slots = () # tuples don't have any writable attributes 2512 2513 def __repr__(self): 2514 return "TupleClass(%s)" % self.formal_type_parameters 2515 2516 def compute_mro(self): 2517 # ParameterizedClass removes the base PyTDClass(tuple) from the mro; add it 2518 # back here so that isinstance(tuple) checks work. 2519 return (self,) + self.base_cls.mro 2520 2521 def get_formal_type_parameters(self): 2522 return {abstract_utils.full_type_name(self, abstract_utils.T): 2523 self.formal_type_parameters[abstract_utils.T]} 2524 2525 def instantiate(self, node, container=None): 2526 if self._instance: 2527 return self._instance.to_variable(node) 2528 content = [] 2529 for i in range(self.tuple_length): 2530 p = self.formal_type_parameters[i] 2531 if container is abstract_utils.DUMMY_CONTAINER or ( 2532 isinstance(container, SimpleValue) and 2533 isinstance(p, TypeParameter) and 2534 p.full_name in container.all_template_names): 2535 content.append(p.instantiate(self.vm.root_node, container)) 2536 else: 2537 content.append(p.instantiate(self.vm.root_node)) 2538 return Tuple(tuple(content), self.vm).to_variable(node) 2539 2540 def _instantiate_index(self, node, index): 2541 if self._instance: 2542 return self._instance.pyval[index] 2543 else: 2544 index %= self.tuple_length # fixes negative indices 2545 return self.formal_type_parameters[index].instantiate(node) 2546 2547 def register_instance(self, instance): 2548 # A TupleClass can never have more than one registered instance because the 2549 # only direct instances of TupleClass are Tuple objects, which create their 2550 # own class upon instantiation. We store the instance in order to track 2551 # changes in the types of the elements (see TupleTest.testMutableItem). 2552 assert not self._instance 2553 self._instance = instance 2554 2555 def getitem_slot(self, node, index_var): 2556 """Implementation of tuple.__getitem__.""" 2557 try: 2558 index = self.vm.convert.value_to_constant( 2559 abstract_utils.get_atomic_value(index_var), (int, slice)) 2560 except abstract_utils.ConversionError: 2561 pass 2562 else: 2563 if isinstance(index, slice): 2564 if self._instance: 2565 slice_content = self._instance.pyval[index] 2566 return node, self.vm.convert.build_tuple(node, slice_content) 2567 else: 2568 # Constructing the tuple directly is faster than calling call_pytd. 2569 instance = Instance(self.vm.convert.tuple_type, self.vm) 2570 node, contained_type = self.vm.init_class( 2571 node, self.formal_type_parameters[abstract_utils.T]) 2572 instance.merge_instance_type_parameter( 2573 node, abstract_utils.T, contained_type) 2574 return node, instance.to_variable(node) 2575 if -self.tuple_length <= index < self.tuple_length: 2576 # Index out of bounds is not a pytype error because of the high 2577 # likelihood of false positives, e.g., 2578 # tup = [] 2579 # idx = 0 2580 # if idx < len(tup): 2581 # tup[idx] 2582 return node, self._instantiate_index(node, index) 2583 return self.call_pytd( 2584 node, "__getitem__", self.instantiate(node), index_var) 2585 2586 def get_special_attribute(self, node, name, valself): 2587 if (valself and not abstract_utils.equivalent_to(valself, self) and 2588 name in self._slots): 2589 return mixin.HasSlots.get_special_attribute(self, node, name, valself) 2590 return super().get_special_attribute(node, name, valself) 2591 2592 2593class CallableClass(ParameterizedClass, mixin.HasSlots): 2594 """A Callable with a list of argument types. 2595 2596 The formal_type_parameters attribute stores the types of the individual 2597 arguments under their indices, the overall argument type under "ARGS", and the 2598 return type under "RET". So for 2599 CallableClass[[int, bool], str] 2600 formal_type_parameters is 2601 {0: int, 1: bool, ARGS: int or bool, RET: str} 2602 When there are no args (CallableClass[[], ...]), ARGS contains abstract.Empty. 2603 """ 2604 2605 def __init__(self, base_cls, formal_type_parameters, vm, template=None): 2606 super().__init__(base_cls, formal_type_parameters, vm, template) 2607 mixin.HasSlots.init_mixin(self) 2608 self.set_slot("__call__", self.call_slot) 2609 # We subtract two to account for "ARGS" and "RET". 2610 self.num_args = len(self.formal_type_parameters) - 2 2611 2612 def __repr__(self): 2613 return "CallableClass(%s)" % self.formal_type_parameters 2614 2615 def get_formal_type_parameters(self): 2616 return { 2617 abstract_utils.full_type_name(self, abstract_utils.ARGS): ( 2618 self.formal_type_parameters[abstract_utils.ARGS]), 2619 abstract_utils.full_type_name(self, abstract_utils.RET): ( 2620 self.formal_type_parameters[abstract_utils.RET])} 2621 2622 def call_slot(self, node, *args, **kwargs): 2623 """Implementation of CallableClass.__call__.""" 2624 if kwargs: 2625 raise function.WrongKeywordArgs( 2626 function.Signature.from_callable(self), 2627 function.Args(posargs=args, namedargs=kwargs), self.vm, kwargs.keys()) 2628 if len(args) != self.num_args: 2629 raise function.WrongArgCount(function.Signature.from_callable(self), 2630 function.Args(posargs=args), self.vm) 2631 formal_args = [(function.argname(i), self.formal_type_parameters[i]) 2632 for i in range(self.num_args)] 2633 substs = [datatypes.AliasingDict()] 2634 bad_param = None 2635 for view in abstract_utils.get_views(args, node): 2636 arg_dict = {function.argname(i): view[args[i]] 2637 for i in range(self.num_args)} 2638 subst, bad_param = self.vm.matcher(node).compute_subst( 2639 formal_args, arg_dict, view, None) 2640 if subst is not None: 2641 substs = [subst] 2642 break 2643 else: 2644 if bad_param: 2645 raise function.WrongArgTypes( 2646 function.Signature.from_callable(self), function.Args(posargs=args), 2647 self.vm, bad_param=bad_param) 2648 ret = self.vm.annotations_util.sub_one_annotation( 2649 node, self.formal_type_parameters[abstract_utils.RET], substs) 2650 node, retvar = self.vm.init_class(node, ret) 2651 return node, retvar 2652 2653 def get_special_attribute(self, node, name, valself): 2654 if (valself and not abstract_utils.equivalent_to(valself, self) and 2655 name in self._slots): 2656 return mixin.HasSlots.get_special_attribute(self, node, name, valself) 2657 return super().get_special_attribute(node, name, valself) 2658 2659 2660class LiteralClass(ParameterizedClass): 2661 """The class of a typing.Literal.""" 2662 2663 def __init__(self, instance, vm, template=None): 2664 base_cls = vm.convert.name_to_value("typing.Literal") 2665 formal_type_parameters = {abstract_utils.T: instance.get_class()} 2666 super().__init__(base_cls, formal_type_parameters, vm, template) 2667 self._instance = instance 2668 2669 def __repr__(self): 2670 return "LiteralClass(%s)" % self._instance 2671 2672 def __eq__(self, other): 2673 if isinstance(other, LiteralClass): 2674 if self.value and other.value: 2675 return self.value.pyval == other.value.pyval 2676 return super().__eq__(other) 2677 2678 def __hash__(self): 2679 return hash((super().__hash__(), self._instance)) 2680 2681 @property 2682 def value(self): 2683 if isinstance(self._instance, ConcreteValue): 2684 return self._instance 2685 # TODO(b/173742489): Remove this workaround once we support literal enums. 2686 return None 2687 2688 def instantiate(self, node, container=None): 2689 return self._instance.to_variable(node) 2690 2691 2692class PyTDClass(SimpleValue, class_mixin.Class, mixin.LazyMembers): 2693 """An abstract wrapper for PyTD class objects. 2694 2695 These are the abstract values for class objects that are described in PyTD. 2696 2697 Attributes: 2698 cls: A pytd.Class 2699 mro: Method resolution order. An iterable of BaseValue. 2700 """ 2701 2702 def __init__(self, name, pytd_cls, vm): 2703 # Apply decorators first, in case they set any properties that later 2704 # initialization code needs to read. 2705 self.has_explicit_init = any(x.name == "__init__" for x in pytd_cls.methods) 2706 pytd_cls, decorated = decorate.process_class(pytd_cls) 2707 self.pytd_cls = pytd_cls 2708 super().__init__(name, vm) 2709 mm = {} 2710 for val in pytd_cls.constants: 2711 if isinstance(val.type, pytd.Annotated): 2712 mm[val.name] = val.Replace(type=val.type.base_type) 2713 else: 2714 mm[val.name] = val 2715 for val in pytd_cls.methods: 2716 mm[val.name] = val 2717 for val in pytd_cls.classes: 2718 mm[val.name.rsplit(".", 1)[-1]] = val 2719 if pytd_cls.metaclass is None: 2720 metaclass = None 2721 else: 2722 metaclass = self.vm.convert.constant_to_value( 2723 pytd_cls.metaclass, 2724 subst=datatypes.AliasingDict(), 2725 node=self.vm.root_node) 2726 self.official_name = self.name 2727 self.slots = pytd_cls.slots 2728 mixin.LazyMembers.init_mixin(self, mm) 2729 self.is_dynamic = self.compute_is_dynamic() 2730 class_mixin.Class.init_mixin(self, metaclass) 2731 if decorated: 2732 self._populate_decorator_metadata() 2733 2734 def _populate_decorator_metadata(self): 2735 """Fill in class attribute metadata for decorators like @dataclass.""" 2736 key = None 2737 keyed_decorator = None 2738 for decorator in self.pytd_cls.decorators: 2739 decorator_name = decorator.type.name 2740 decorator_key = class_mixin.get_metadata_key(decorator_name) 2741 if decorator_key: 2742 if key: 2743 error = f"Cannot apply both @{keyed_decorator} and @{decorator}." 2744 self.vm.errorlog.invalid_annotation(self.vm.frames, self, error) 2745 else: 2746 key, keyed_decorator = decorator_key, decorator 2747 self._init_attr_metadata_from_pytd(decorator_name) 2748 self._recompute_init_from_metadata(key) 2749 2750 def _init_attr_metadata_from_pytd(self, decorator): 2751 """Initialise metadata[key] with a list of Attributes.""" 2752 # Use the __init__ function as the source of truth for dataclass fields; if 2753 # this is a generated module we will have already processed ClassVar and 2754 # InitVar attributes to generate __init__, so the fields we want to add to 2755 # the subclass __init__ are the init params rather than the full list of 2756 # class attributes. 2757 init = next(x for x in self.pytd_cls.methods if x.name == "__init__") 2758 params = init.signatures[0].params[1:] 2759 with self.vm.allow_recursive_convert(): 2760 own_attrs = [class_mixin.Attribute.from_param(p, self.vm) for p in params] 2761 self.compute_attr_metadata(own_attrs, decorator) 2762 2763 def _recompute_init_from_metadata(self, key): 2764 # Some decorated classes (dataclasses e.g.) have their __init__ function 2765 # set via traversing the MRO to collect initializers from decorated parent 2766 # classes as well. Since we don't have access to the MRO when initially 2767 # decorating the class, we recalculate the __init__ signature from the 2768 # combined attribute list in the metadata. 2769 if self.has_explicit_init: 2770 # Do not override an __init__ from the pyi file 2771 return 2772 attrs = self.metadata[key] 2773 fields = [x.to_pytd_constant() for x in attrs] 2774 self.pytd_cls = decorate.add_init_from_fields(self.pytd_cls, fields) 2775 init = self.pytd_cls.Lookup("__init__") 2776 self._member_map["__init__"] = init 2777 2778 def get_own_attributes(self): 2779 return {name for name, member in self._member_map.items()} 2780 2781 def get_own_abstract_methods(self): 2782 return {name for name, member in self._member_map.items() 2783 if isinstance(member, pytd.Function) and member.is_abstract} 2784 2785 def bases(self): 2786 convert = self.vm.convert 2787 return [ 2788 convert.constant_to_var( 2789 parent, subst=datatypes.AliasingDict(), node=self.vm.root_node) 2790 for parent in self.pytd_cls.parents 2791 ] 2792 2793 def load_lazy_attribute(self, name, subst=None): 2794 try: 2795 super().load_lazy_attribute(name, subst) 2796 except self.vm.convert.TypeParameterError as e: 2797 self.vm.errorlog.unbound_type_param( 2798 self.vm.frames, self, name, e.type_param_name) 2799 self.members[name] = self.vm.new_unsolvable(self.vm.root_node) 2800 2801 def _convert_member(self, member, subst=None): 2802 """Convert a member as a variable. For lazy lookup.""" 2803 subst = subst or datatypes.AliasingDict() 2804 node = self.vm.root_node 2805 if isinstance(member, pytd.Constant): 2806 return self.vm.convert.constant_to_var( 2807 abstract_utils.AsInstance(member.type), subst, node) 2808 elif isinstance(member, pytd.Function): 2809 c = self.vm.convert.constant_to_value(member, subst=subst, node=node) 2810 c.parent = self 2811 return c.to_variable(node) 2812 elif isinstance(member, pytd.Class): 2813 return self.vm.convert.constant_to_var(member, subst=subst, node=node) 2814 else: 2815 raise AssertionError("Invalid class member %s" % pytd_utils.Print(member)) 2816 2817 def call(self, node, func, args, alias_map=None): 2818 if self.is_abstract and not self.from_annotation: 2819 self.vm.errorlog.not_instantiable(self.vm.frames, self) 2820 node, results = self._call_new_and_init(node, func, args) 2821 if results is None: 2822 if self.full_name == "builtins.tuple" and args.is_empty(): 2823 value = Tuple((), self.vm) 2824 elif self.full_name == "builtins.dict" and args.is_empty(): 2825 value = Dict(self.vm) 2826 else: 2827 value = Instance( 2828 self.vm.convert.constant_to_value(self.pytd_cls), self.vm) 2829 for type_param in self.template: 2830 name = type_param.full_name 2831 if name not in value.instance_type_parameters: 2832 value.instance_type_parameters[name] = self.vm.program.NewVariable() 2833 results = self.vm.program.NewVariable() 2834 retval = results.AddBinding(value, [func], node) 2835 node = self._call_init(node, retval, args) 2836 return node, results 2837 2838 def instantiate(self, node, container=None): 2839 return self.vm.convert.constant_to_var( 2840 abstract_utils.AsInstance(self.pytd_cls), {}, node) 2841 2842 def __repr__(self): 2843 return "PyTDClass(%s)" % self.name 2844 2845 def __contains__(self, name): 2846 return name in self._member_map 2847 2848 def convert_as_instance_attribute(self, name, instance): 2849 """Convert `name` as an instance attribute. 2850 2851 This method is used by attribute.py to lazily load attributes on instances 2852 of this PyTDClass. Calling this method directly should be avoided. Doing so 2853 will create multiple copies of the same attribute, leading to subtle bugs. 2854 2855 Args: 2856 name: The attribute name. 2857 instance: An instance of this PyTDClass. 2858 2859 Returns: 2860 The converted attribute. 2861 """ 2862 try: 2863 c = self.pytd_cls.Lookup(name) 2864 except KeyError: 2865 return None 2866 if isinstance(c, pytd.Constant): 2867 try: 2868 self._convert_member(c) 2869 except self.vm.convert.TypeParameterError: 2870 # Constant c cannot be converted without type parameter substitutions, 2871 # so it must be an instance attribute. 2872 subst = datatypes.AliasingDict() 2873 for itm in self.pytd_cls.template: 2874 subst[itm.full_name] = self.vm.convert.constant_to_value( 2875 itm.type_param, {}).instantiate( 2876 self.vm.root_node, container=instance) 2877 return self._convert_member(c, subst) 2878 2879 def generate_ast(self): 2880 """Generate this class's AST, including updated members.""" 2881 return pytd.Class( 2882 name=self.name, 2883 metaclass=self.pytd_cls.metaclass, 2884 parents=self.pytd_cls.parents, 2885 methods=tuple(self._member_map[m.name] for m in self.pytd_cls.methods), 2886 constants=self.pytd_cls.constants, 2887 classes=self.pytd_cls.classes, 2888 decorators=self.pytd_cls.decorators, 2889 slots=self.pytd_cls.slots, 2890 template=self.pytd_cls.template) 2891 2892 2893class FunctionPyTDClass(PyTDClass): 2894 """PyTDClass(Callable) subclass to support annotating higher-order functions. 2895 2896 In InterpreterFunction calls, type parameter annotations are handled by 2897 getting the types of the parameters from the arguments and instantiating them 2898 in the return value. To handle a signature like (func: T) -> T, we need to 2899 save the value of `func`, not just its type of Callable. 2900 """ 2901 2902 def __init__(self, func, vm): 2903 super().__init__("typing.Callable", vm.convert.function_type.pytd_cls, vm) 2904 self.func = func 2905 2906 def instantiate(self, node, container=None): 2907 del container # unused 2908 return self.func.to_variable(node) 2909 2910 2911class InterpreterClass(SimpleValue, class_mixin.Class): 2912 """An abstract wrapper for user-defined class objects. 2913 2914 These are the abstract value for class objects that are implemented in the 2915 program. 2916 """ 2917 2918 def __init__(self, name, bases, members, cls, vm): 2919 assert isinstance(name, str) 2920 assert isinstance(bases, list) 2921 assert isinstance(members, dict) 2922 self._bases = bases 2923 super().__init__(name, vm) 2924 self.members = datatypes.MonitorDict(members) 2925 class_mixin.Class.init_mixin(self, cls) 2926 self.instances = set() # filled through register_instance 2927 # instances created by analyze.py for the purpose of analyzing this class, 2928 # a subset of 'instances'. Filled through register_canonical_instance. 2929 self.canonical_instances = set() 2930 self.slots = self._convert_slots(members.get("__slots__")) 2931 self.is_dynamic = self.compute_is_dynamic() 2932 log.info("Created class: %r", self) 2933 self.type_param_check() 2934 self.decorators = [] 2935 2936 def update_signature_scope(self, method): 2937 method.signature.excluded_types.update( 2938 [t.name for t in self.template]) 2939 method.signature.add_scope(self.full_name) 2940 2941 def update_method_type_params(self): 2942 if self.template: 2943 # For function type parameters check 2944 for mbr in self.members.values(): 2945 m = abstract_utils.get_atomic_value( 2946 mbr, default=self.vm.convert.unsolvable) 2947 if isinstance(m, SignedFunction): 2948 self.update_signature_scope(m) 2949 elif mbr.data and all( 2950 x.__class__.__name__ == "PropertyInstance" for x in mbr.data): 2951 # We generate a new variable every time we add a property slot, so we 2952 # take the last one (which contains bindings for all defined slots). 2953 prop = mbr.data[-1] 2954 for slot in (prop.fget, prop.fset, prop.fdel): 2955 if slot: 2956 for d in slot.data: 2957 if isinstance(d, SignedFunction): 2958 self.update_signature_scope(d) 2959 2960 def type_param_check(self): 2961 """Throw exception for invalid type parameters.""" 2962 self.update_method_type_params() 2963 if self.template: 2964 # nested class can not use the same type parameter 2965 # in current generic class 2966 inner_cls_types = self.collect_inner_cls_types() 2967 for cls, item in inner_cls_types: 2968 nitem = item.with_module(self.full_name) 2969 if nitem in self.template: 2970 raise abstract_utils.GenericTypeError( 2971 self, ("Generic class [%s] and its nested generic class [%s] " 2972 "cannot use the same type variable %s.") 2973 % (self.full_name, cls.full_name, item.name)) 2974 2975 self._load_all_formal_type_parameters() # Throw exception if there is error 2976 for t in self.template: 2977 if t.full_name in self.all_formal_type_parameters: 2978 raise abstract_utils.GenericTypeError( 2979 self, "Conflicting value for TypeVar %s" % t.full_name) 2980 2981 def collect_inner_cls_types(self, max_depth=5): 2982 """Collect all the type parameters from nested classes.""" 2983 templates = set() 2984 if max_depth > 0: 2985 for mbr in self.members.values(): 2986 mbr = abstract_utils.get_atomic_value( 2987 mbr, default=self.vm.convert.unsolvable) 2988 if isinstance(mbr, InterpreterClass) and mbr.template: 2989 templates.update([(mbr, item.with_module(None)) 2990 for item in mbr.template]) 2991 templates.update(mbr.collect_inner_cls_types(max_depth - 1)) 2992 return templates 2993 2994 def get_inner_classes(self): 2995 """Return the list of top-level nested classes.""" 2996 values = [ 2997 abstract_utils.get_atomic_value(mbr, default=self.vm.convert.unsolvable) 2998 for mbr in self.members.values()] 2999 return [x for x in values if isinstance(x, InterpreterClass)] 3000 3001 def get_own_attributes(self): 3002 attributes = set(self.members) 3003 annotations_dict = abstract_utils.get_annotations_dict(self.members) 3004 if annotations_dict: 3005 attributes.update(annotations_dict.annotated_locals) 3006 return attributes - abstract_utils.CLASS_LEVEL_IGNORE 3007 3008 def get_own_abstract_methods(self): 3009 def _can_be_abstract(var): 3010 return any((isinstance(v, Function) or v.isinstance_PropertyInstance()) 3011 and v.is_abstract for v in var.data) 3012 return {name for name, var in self.members.items() if _can_be_abstract(var)} 3013 3014 def _mangle(self, name): 3015 """Do name-mangling on an attribute name. 3016 3017 See https://goo.gl/X85fHt. Python automatically converts a name like 3018 "__foo" to "_ClassName__foo" in the bytecode. (But "forgets" to do so in 3019 other places, e.g. in the strings of __slots__.) 3020 3021 Arguments: 3022 name: The name of an attribute of the current class. E.g. "__foo". 3023 3024 Returns: 3025 The mangled name. E.g. "_MyClass__foo". 3026 """ 3027 if name.startswith("__") and not name.endswith("__"): 3028 return "_" + self.name + name 3029 else: 3030 return name 3031 3032 def _convert_slots(self, slots_var): 3033 """Convert __slots__ from a Variable to a tuple.""" 3034 if slots_var is None: 3035 return None 3036 if len(slots_var.bindings) != 1: 3037 # Ambiguous slots 3038 return None # Treat "unknown __slots__" and "no __slots__" the same. 3039 val = slots_var.data[0] 3040 if isinstance(val, mixin.PythonConstant): 3041 if isinstance(val.pyval, (list, tuple)): 3042 entries = val.pyval 3043 else: 3044 return None # Happens e.g. __slots__ = {"foo", "bar"}. Not an error. 3045 else: 3046 return None # Happens e.g. for __slots__ = dir(Foo) 3047 try: 3048 names = [abstract_utils.get_atomic_python_constant(v) for v in entries] 3049 except abstract_utils.ConversionError: 3050 return None # Happens e.g. for __slots__ = ["x" if b else "y"] 3051 # Slot names should be strings. 3052 for s in names: 3053 if not isinstance(s, str): 3054 self.vm.errorlog.bad_slots( 3055 self.vm.frames, "Invalid __slot__ entry: %r" % str(s)) 3056 return None 3057 return tuple(self._mangle(s) for s in names) 3058 3059 def register_instance(self, instance): 3060 self.instances.add(instance) 3061 3062 def register_canonical_instance(self, instance): 3063 self.canonical_instances.add(instance) 3064 3065 def bases(self): 3066 return self._bases 3067 3068 def metaclass(self, node): 3069 if self.cls and self.cls is not self._get_inherited_metaclass(): 3070 return self.vm.convert.merge_classes([self]) 3071 else: 3072 return None 3073 3074 def instantiate(self, node, container=None): 3075 if self.vm.frame and self.vm.frame.current_opcode: 3076 return self._new_instance(container).to_variable(node) 3077 else: 3078 # When the analyze_x methods in CallTracer instantiate classes in 3079 # preparation for analysis, often there is no frame on the stack yet, or 3080 # the frame is a SimpleFrame with no opcode. 3081 return super().instantiate(node, container) 3082 3083 def __repr__(self): 3084 return "InterpreterClass(%s)" % self.name 3085 3086 def __contains__(self, name): 3087 if name in self.members: 3088 return True 3089 annotations_dict = abstract_utils.get_annotations_dict(self.members) 3090 return annotations_dict and name in annotations_dict.annotated_locals 3091 3092 def update_official_name(self, name): 3093 assert isinstance(name, str) 3094 if (self.official_name is None or 3095 name == self.name or 3096 (self.official_name != self.name and name < self.official_name)): 3097 # The lexical comparison is to ensure that, in the case of multiple calls 3098 # to this method, the official name does not depend on the call order. 3099 self.official_name = name 3100 3101 3102class NativeFunction(Function): 3103 """An abstract value representing a native function. 3104 3105 Attributes: 3106 name: Function name. Might just be something like "<lambda>". 3107 func: An object with a __call__ method. 3108 vm: TypegraphVirtualMachine instance. 3109 """ 3110 3111 def __init__(self, name, func, vm): 3112 super().__init__(name, vm) 3113 self.func = func 3114 self.bound_class = lambda callself, underlying: self 3115 3116 def argcount(self, _): 3117 return self.func.func_code.co_argcount 3118 3119 def call(self, node, _, args, alias_map=None): 3120 sig = None 3121 if isinstance(self.func.__self__, CallableClass): 3122 sig = function.Signature.from_callable(self.func.__self__) 3123 args = args.simplify(node, self.vm, match_signature=sig) 3124 posargs = [u.AssignToNewVariable(node) for u in args.posargs] 3125 namedargs = {k: u.AssignToNewVariable(node) 3126 for k, u in args.namedargs.items()} 3127 try: 3128 inspect.signature(self.func).bind(node, *posargs, **namedargs) 3129 except ValueError as e: 3130 # Happens for, e.g., 3131 # def f((x, y)): pass 3132 # f((42,)) 3133 raise NotImplementedError("Wrong number of values to unpack") from e 3134 except TypeError as e: 3135 # The possible errors here are: 3136 # (1) wrong arg count 3137 # (2) duplicate keyword 3138 # (3) unexpected keyword 3139 # The way we constructed namedargs rules out (2). 3140 if "keyword" in utils.message(e): 3141 # Happens for, e.g., 3142 # def f(*args): pass 3143 # f(x=42) 3144 raise NotImplementedError("Unexpected keyword") from e 3145 # The function was passed the wrong number of arguments. The signature is 3146 # ([self, ]node, ...). The length of "..." tells us how many variables 3147 # are expected. 3148 expected_argcount = len(inspect.getfullargspec(self.func).args) - 1 3149 if inspect.ismethod(self.func) and self.func.__self__ is not None: 3150 expected_argcount -= 1 3151 actual_argcount = len(posargs) + len(namedargs) 3152 if (actual_argcount > expected_argcount or 3153 (not args.starargs and not args.starstarargs)): 3154 # If we have too many arguments, or starargs and starstarargs are both 3155 # empty, then we can be certain of a WrongArgCount error. 3156 argnames = tuple("_" + str(i) for i in range(expected_argcount)) 3157 sig = function.Signature( 3158 self.name, argnames, None, set(), None, {}, {}, {}) 3159 raise function.WrongArgCount(sig, args, self.vm) 3160 assert actual_argcount < expected_argcount 3161 # Assume that starargs or starstarargs fills in the missing arguments. 3162 # Instead of guessing where these arguments should go, overwrite all of 3163 # the arguments with a list of unsolvables of the correct length, which 3164 # is guaranteed to give us a correct (but imprecise) analysis. 3165 posargs = [self.vm.new_unsolvable(node) 3166 for _ in range(expected_argcount)] 3167 namedargs = {} 3168 return self.func(node, *posargs, **namedargs) 3169 3170 def get_positional_names(self): 3171 code = self.func.func_code 3172 return list(code.co_varnames[:code.co_argcount]) 3173 3174 3175class SignedFunction(Function): 3176 """An abstract base class for functions represented by function.Signature. 3177 3178 Subclasses should define call(self, node, f, args) and set self.bound_class. 3179 """ 3180 3181 def __init__(self, signature, vm): 3182 super().__init__(signature.name, vm) 3183 self.signature = signature 3184 # Track whether we've annotated `self` with `set_self_annot`, since 3185 # annotating `self` in `__init__` is otherwise illegal. 3186 self._has_self_annot = False 3187 3188 @contextlib.contextmanager 3189 def set_self_annot(self, annot_class): 3190 """Set the annotation for `self` in a class.""" 3191 self_name = self.signature.param_names[0] 3192 old_self = self.signature.annotations.get(self_name) 3193 old_has_self_annot = self._has_self_annot 3194 self.signature.annotations[self_name] = annot_class 3195 self._has_self_annot = True 3196 try: 3197 yield 3198 finally: 3199 if old_self: 3200 self.signature.annotations[self_name] = old_self 3201 else: 3202 del self.signature.annotations[self_name] 3203 self._has_self_annot = old_has_self_annot 3204 3205 def argcount(self, _): 3206 return len(self.signature.param_names) 3207 3208 def get_nondefault_params(self): 3209 return ((n, n in self.signature.kwonly_params) 3210 for n in self.signature.param_names 3211 if n not in self.signature.defaults) 3212 3213 def match_and_map_args(self, node, args, alias_map): 3214 """Calls match_args() and _map_args().""" 3215 return self.match_args(node, args, alias_map), self._map_args(node, args) 3216 3217 def _map_args(self, node, args): 3218 """Map call args to function args. 3219 3220 This emulates how Python would map arguments of function calls. It takes 3221 care of keyword parameters, default parameters, and *args and **kwargs. 3222 3223 Args: 3224 node: The current CFG node. 3225 args: The arguments. 3226 3227 Returns: 3228 A dictionary, mapping strings (parameter names) to cfg.Variable. 3229 3230 Raises: 3231 function.FailedFunctionCall: If the caller supplied incorrect arguments. 3232 """ 3233 # Originate a new variable for each argument and call. 3234 posargs = [u.AssignToNewVariable(node) 3235 for u in args.posargs] 3236 kws = {k: u.AssignToNewVariable(node) 3237 for k, u in args.namedargs.items()} 3238 sig = self.signature 3239 callargs = {name: self.vm.program.NewVariable(default.data, [], node) 3240 for name, default in sig.defaults.items()} 3241 positional = dict(zip(sig.param_names, posargs)) 3242 for key in positional: 3243 if key in kws: 3244 raise function.DuplicateKeyword(sig, args, self.vm, key) 3245 extra_kws = set(kws).difference(sig.param_names + sig.kwonly_params) 3246 if extra_kws and not sig.kwargs_name: 3247 raise function.WrongKeywordArgs(sig, args, self.vm, extra_kws) 3248 callargs.update(positional) 3249 callargs.update(kws) 3250 for key, kwonly in self.get_nondefault_params(): 3251 if key not in callargs: 3252 if args.starstarargs or (args.starargs and not kwonly): 3253 # We assume that because we have *args or **kwargs, we can use these 3254 # to fill in any parameters we might be missing. 3255 callargs[key] = self.vm.new_unsolvable(node) 3256 else: 3257 raise function.MissingParameter(sig, args, self.vm, key) 3258 for key in sig.kwonly_params: 3259 if key not in callargs: 3260 raise function.MissingParameter(sig, args, self.vm, key) 3261 if sig.varargs_name: 3262 varargs_name = sig.varargs_name 3263 extraneous = posargs[self.argcount(node):] 3264 if args.starargs: 3265 if extraneous: 3266 log.warning("Not adding extra params to *%s", varargs_name) 3267 callargs[varargs_name] = args.starargs.AssignToNewVariable(node) 3268 else: 3269 callargs[varargs_name] = self.vm.convert.build_tuple(node, extraneous) 3270 elif len(posargs) > self.argcount(node): 3271 raise function.WrongArgCount(sig, args, self.vm) 3272 if sig.kwargs_name: 3273 kwargs_name = sig.kwargs_name 3274 # Build a **kwargs dictionary out of the extraneous parameters 3275 if args.starstarargs: 3276 callargs[kwargs_name] = args.starstarargs.AssignToNewVariable(node) 3277 else: 3278 omit = sig.param_names + sig.kwonly_params 3279 k = Dict(self.vm) 3280 k.update(node, args.namedargs, omit=omit) 3281 callargs[kwargs_name] = k.to_variable(node) 3282 return callargs 3283 3284 def _match_view(self, node, args, view, alias_map=None): 3285 arg_dict = {} 3286 formal_args = [] 3287 for name, arg, formal in self.signature.iter_args(args): 3288 arg_dict[name] = view[arg] 3289 if formal is not None: 3290 if name in (self.signature.varargs_name, self.signature.kwargs_name): 3291 # The annotation is Tuple or Dict, but the passed arg only has to be 3292 # Iterable or Mapping. 3293 formal = self.vm.convert.widen_type(formal) 3294 formal_args.append((name, formal)) 3295 subst, bad_arg = self.vm.matcher(node).compute_subst( 3296 formal_args, arg_dict, view, alias_map) 3297 if subst is None: 3298 raise function.WrongArgTypes( 3299 self.signature, args, self.vm, bad_param=bad_arg) 3300 return subst 3301 3302 def get_first_opcode(self): 3303 return None 3304 3305 def set_function_defaults(self, node, defaults_var): 3306 """Attempts to set default arguments of a function. 3307 3308 If defaults_var is not an unambiguous tuple (i.e. one that can be processed 3309 by abstract_utils.get_atomic_python_constant), every argument is made 3310 optional and a warning is issued. This function emulates __defaults__. 3311 3312 Args: 3313 node: The node where default arguments are being set. Needed if we cannot 3314 get a useful value from defaults_var. 3315 defaults_var: a Variable with a single binding to a tuple of default 3316 values. 3317 """ 3318 defaults = self._extract_defaults(defaults_var) 3319 if defaults is None: 3320 defaults = [self.vm.new_unsolvable(node) 3321 for _ in self.signature.param_names] 3322 defaults = dict(zip(self.signature.param_names[-len(defaults):], defaults)) 3323 self.signature.defaults = defaults 3324 3325 def _mutations_generator(self, node, first_arg, substs): 3326 def generator(): 3327 """Yields mutations.""" 3328 if (not (self.is_attribute_of_class or self.name == "__new__") or 3329 not first_arg or not substs): 3330 return 3331 try: 3332 inst = abstract_utils.get_atomic_value(first_arg, Instance) 3333 except abstract_utils.ConversionError: 3334 return 3335 if inst.cls.template: 3336 for subst in substs: 3337 for k, v in subst.items(): 3338 if k in inst.instance_type_parameters: 3339 value = inst.instance_type_parameters[k].AssignToNewVariable(node) 3340 if all(isinstance(val, Unknown) for val in v.data): 3341 for param in inst.cls.template: 3342 if subst.same_name(k, param.full_name): 3343 value.PasteVariable(param.instantiate(node), node) 3344 break 3345 else: 3346 # See GenericFeatureTest.test_reinherit_generic in 3347 # tests/test_generic2. This can happen if one generic class 3348 # inherits from another and separately reuses a TypeVar. 3349 value.PasteVariable(v, node) 3350 else: 3351 value.PasteVariable(v, node) 3352 yield function.Mutation(inst, k, value) 3353 # Optimization: return a generator to avoid iterating over the mutations an 3354 # extra time. 3355 return generator 3356 3357 3358class InterpreterFunction(SignedFunction): 3359 """An abstract value representing a user-defined function. 3360 3361 Attributes: 3362 name: Function name. Might just be something like "<lambda>". 3363 code: A code object. 3364 closure: Tuple of cells (cfg.Variable) containing the free variables 3365 this closure binds to. 3366 vm: TypegraphVirtualMachine instance. 3367 """ 3368 3369 _function_cache = {} 3370 3371 @classmethod 3372 def make(cls, name, code, f_locals, f_globals, defaults, kw_defaults, closure, 3373 annotations, vm): 3374 """Get an InterpreterFunction. 3375 3376 Things like anonymous functions and generator expressions are created 3377 every time the corresponding code executes. Caching them makes it easier 3378 to detect when the environment hasn't changed and a function call can be 3379 optimized away. 3380 3381 Arguments: 3382 name: Function name. 3383 code: A code object. 3384 f_locals: The locals used for name resolution. 3385 f_globals: The globals used for name resolution. 3386 defaults: Default arguments. 3387 kw_defaults: Default arguments for kwonly parameters. 3388 closure: The free variables this closure binds to. 3389 annotations: Function annotations. Dict of name -> BaseValue. 3390 vm: VirtualMachine instance. 3391 3392 Returns: 3393 An InterpreterFunction. 3394 """ 3395 annotations = annotations or {} 3396 if "return" in annotations: 3397 # Check Generator/AsyncGenerator return type 3398 ret_type = annotations["return"] 3399 if code.has_generator(): 3400 if not abstract_utils.matches_generator(ret_type): 3401 vm.errorlog.bad_yield_annotation( 3402 vm.frames, name, ret_type, is_async=False) 3403 elif code.has_async_generator(): 3404 if not abstract_utils.matches_async_generator(ret_type): 3405 vm.errorlog.bad_yield_annotation( 3406 vm.frames, name, ret_type, is_async=True) 3407 overloads = vm.frame.overloads[name] 3408 key = (name, code, 3409 abstract_utils.hash_all_dicts( 3410 (f_globals.members, set(code.co_names)), 3411 (f_locals.members, 3412 set(f_locals.members) - set(code.co_varnames)), ({ 3413 key: vm.program.NewVariable([value], [], vm.root_node) 3414 for key, value in annotations.items() 3415 }, None), (dict( 3416 enumerate( 3417 vm.program.NewVariable([f], [], vm.root_node) 3418 for f in overloads)), None), 3419 (dict(enumerate(defaults)), None), 3420 (dict(enumerate(closure or ())), None))) 3421 if key not in cls._function_cache: 3422 cls._function_cache[key] = cls( 3423 name, code, f_locals, f_globals, defaults, kw_defaults, closure, 3424 annotations, overloads, vm) 3425 return cls._function_cache[key] 3426 3427 def __init__(self, name, code, f_locals, f_globals, defaults, kw_defaults, 3428 closure, annotations, overloads, vm): 3429 log.debug("Creating InterpreterFunction %r for %r", name, code.co_name) 3430 self.bound_class = BoundInterpreterFunction 3431 self.doc = code.co_consts[0] if code.co_consts else None 3432 self.code = code 3433 self.f_globals = f_globals 3434 self.f_locals = f_locals 3435 self.defaults = tuple(defaults) 3436 self.kw_defaults = kw_defaults 3437 self.closure = closure 3438 self._call_cache = {} 3439 self._call_records = [] 3440 # TODO(b/78034005): Combine this and PyTDFunction.signatures into a single 3441 # way to handle multiple signatures that SignedFunction can also use. 3442 self._overloads = overloads 3443 self.has_overloads = bool(overloads) 3444 self.is_overload = False # will be set by typing_overlay.Overload.call 3445 self.nonstararg_count = self.code.co_argcount 3446 if self.code.co_kwonlyargcount >= 0: # This is usually -1 or 0 (fast call) 3447 self.nonstararg_count += self.code.co_kwonlyargcount 3448 signature = self._build_signature(name, annotations) 3449 super().__init__(signature, vm) 3450 self._update_signature_scope() 3451 self.last_frame = None # for BuildClass 3452 self._store_call_records = False 3453 self.is_class_builder = False # Will be set by BuildClass. 3454 if name.endswith(".__init_subclass__"): 3455 # __init_subclass__ is automatically promoted to a classmethod 3456 self.is_classmethod = True 3457 3458 @contextlib.contextmanager 3459 def record_calls(self): 3460 """Turn on recording of function calls. Used by analyze.py.""" 3461 old = self._store_call_records 3462 self._store_call_records = True 3463 yield 3464 self._store_call_records = old 3465 3466 def _build_signature(self, name, annotations): 3467 """Build a function.Signature object representing this function.""" 3468 vararg_name = None 3469 kwarg_name = None 3470 kwonly = set(self.code.co_varnames[ 3471 self.code.co_argcount:self.nonstararg_count]) 3472 arg_pos = self.nonstararg_count 3473 if self.has_varargs(): 3474 vararg_name = self.code.co_varnames[arg_pos] 3475 arg_pos += 1 3476 if self.has_kwargs(): 3477 kwarg_name = self.code.co_varnames[arg_pos] 3478 arg_pos += 1 3479 defaults = dict(zip( 3480 self.get_positional_names()[-len(self.defaults):], self.defaults)) 3481 defaults.update(self.kw_defaults) 3482 return function.Signature( 3483 name, 3484 tuple(self.code.co_varnames[:self.code.co_argcount]), 3485 vararg_name, 3486 tuple(kwonly), 3487 kwarg_name, 3488 defaults, 3489 annotations) 3490 3491 def _update_signature_scope(self): 3492 # If this is a nested function in an instance method and the nested function 3493 # accesses 'self', then the first variable in the closure is 'self'. We use 3494 # 'self' to update the scopes of any type parameters in the nested method's 3495 # signature to the containing class. 3496 if not self.closure: 3497 return 3498 maybe_instance = self.closure[0] 3499 try: 3500 instance = abstract_utils.get_atomic_value(maybe_instance, Instance) 3501 except abstract_utils.ConversionError: 3502 return 3503 if isinstance(instance.cls, InterpreterClass): 3504 instance.cls.update_signature_scope(self) 3505 3506 def get_first_opcode(self): 3507 return self.code.first_opcode 3508 3509 def argcount(self, _): 3510 return self.code.co_argcount 3511 3512 def match_args(self, node, args, alias_map=None, match_all_views=False): 3513 if not self.signature.has_param_annotations: 3514 return 3515 return super().match_args(node, args, alias_map, match_all_views) 3516 3517 def _inner_cls_check(self, last_frame): 3518 """Check if the function and its nested class use same type parameter.""" 3519 # get all type parameters from function annotations 3520 all_type_parameters = [] 3521 for annot in self.signature.annotations.values(): 3522 params = self.vm.annotations_util.get_type_parameters(annot) 3523 all_type_parameters.extend(itm.with_module(None) for itm in params) 3524 3525 if all_type_parameters: 3526 for key, value in last_frame.f_locals.pyval.items(): 3527 value = abstract_utils.get_atomic_value( 3528 value, default=self.vm.convert.unsolvable) 3529 if (isinstance(value, InterpreterClass) and value.template and 3530 key == value.name): 3531 # `value` is a nested class definition. 3532 inner_cls_types = value.collect_inner_cls_types() 3533 inner_cls_types.update([(value, item.with_module(None)) 3534 for item in value.template]) 3535 # Report errors in a deterministic order. 3536 for cls, item in sorted(inner_cls_types, key=lambda typ: typ[1].name): 3537 if item in all_type_parameters: 3538 self.vm.errorlog.invalid_annotation( 3539 self.vm.simple_stack(self.get_first_opcode()), item, 3540 ("Function [%s] and its nested generic class [%s] cannot use " 3541 "the same type variable %s") 3542 % (self.full_name, cls.full_name, item.name)) 3543 3544 def signature_functions(self): 3545 """Get the functions that describe this function's signature.""" 3546 return self._overloads or [self] 3547 3548 def iter_signature_functions(self): 3549 """Loop through signatures, setting each as the primary one in turn.""" 3550 if not self._overloads: 3551 yield self 3552 return 3553 for f in self._overloads: 3554 old_overloads = self._overloads 3555 self._overloads = [f] 3556 try: 3557 yield f 3558 finally: 3559 self._overloads = old_overloads 3560 3561 def _find_matching_sig(self, node, args, alias_map): 3562 error = None 3563 for f in self.signature_functions(): 3564 try: 3565 # match_args and _map_args both do some matching, so together they fully 3566 # type-check the arguments. 3567 substs, callargs = f.match_and_map_args(node, args, alias_map) 3568 except function.FailedFunctionCall as e: 3569 if e > error: 3570 error = e 3571 else: 3572 # We use the first matching overload. 3573 return f.signature, substs, callargs 3574 raise error # pylint: disable=raising-bad-type 3575 3576 def _set_callself_maybe_missing_members(self): 3577 if self.vm.callself_stack: 3578 for b in self.vm.callself_stack[-1].bindings: 3579 b.data.maybe_missing_members = True 3580 3581 def call(self, node, func, args, new_locals=False, alias_map=None, 3582 frame_substs=()): 3583 if self.is_overload: 3584 raise function.NotCallable(self) 3585 if (self.vm.is_at_maximum_depth() and 3586 not abstract_utils.func_name_is_class_init(self.name)): 3587 log.info("Maximum depth reached. Not analyzing %r", self.name) 3588 self._set_callself_maybe_missing_members() 3589 return node, self.vm.new_unsolvable(node) 3590 args = args.simplify(node, self.vm, self.signature) 3591 sig, substs, callargs = self._find_matching_sig(node, args, alias_map) 3592 if sig is not self.signature: 3593 # We've matched an overload; remap the callargs using the implementation 3594 # so that optional parameters, etc, are correctly defined. 3595 callargs = self._map_args(node, args) 3596 first_arg = sig.get_first_arg(callargs) 3597 annotation_substs = substs 3598 # Adds type parameter substitutions from all containing classes. Note that 3599 # lower frames (ones closer to the end of self.vm.frames) take precedence 3600 # over higher ones. 3601 for frame in reversed(self.vm.frames): 3602 annotation_substs = abstract_utils.combine_substs( 3603 frame.substs, annotation_substs) 3604 # Keep type parameters without substitutions, as they may be needed for 3605 # type-checking down the road. 3606 annotations = self.vm.annotations_util.sub_annotations( 3607 node, sig.annotations, annotation_substs, instantiate_unbound=False) 3608 if sig.has_param_annotations: 3609 if first_arg and sig.param_names[0] == "self": 3610 try: 3611 maybe_container = abstract_utils.get_atomic_value(first_arg) 3612 except abstract_utils.ConversionError: 3613 container = None 3614 else: 3615 cls = maybe_container.cls 3616 if (isinstance(cls, InterpreterClass) or 3617 isinstance(cls, ParameterizedClass) and 3618 isinstance(cls.base_cls, InterpreterClass)): 3619 container = maybe_container 3620 else: 3621 container = None 3622 else: 3623 container = None 3624 for name in callargs: 3625 if (name in annotations and (not self.is_attribute_of_class or 3626 self.argcount(node) == 0 or 3627 name != sig.param_names[0])): 3628 extra_key = (self.get_first_opcode(), name) 3629 node, callargs[name] = self.vm.annotations_util.init_annotation( 3630 node, name, annotations[name], container=container, 3631 extra_key=extra_key) 3632 mutations = self._mutations_generator(node, first_arg, substs) 3633 node = abstract_utils.apply_mutations(node, mutations) 3634 if substs: 3635 frame_substs = tuple(itertools.chain(frame_substs, substs)) 3636 try: 3637 frame = self.vm.make_frame( 3638 node, self.code, self.f_globals, self.f_locals, callargs, 3639 self.closure, new_locals=new_locals, func=func, 3640 first_arg=first_arg, substs=frame_substs) 3641 except self.vm.VirtualMachineRecursionError: 3642 # If we've encountered recursion in a constructor, then we have another 3643 # incompletely initialized instance of the same class (or a subclass) at 3644 # the same node. (See, e.g., testRecursiveConstructor and 3645 # testRecursiveConstructorSubclass in test_classes.ClassesTest.) If we 3646 # allow the VirtualMachineRecursionError to be raised, initialization of 3647 # that first instance will be aborted. Instead, mark this second instance 3648 # as incomplete. 3649 self._set_callself_maybe_missing_members() 3650 return node, self.vm.new_unsolvable(node) 3651 caller_is_abstract = abstract_utils.check_classes( 3652 first_arg, lambda cls: cls.is_abstract) 3653 caller_is_protocol = abstract_utils.check_classes( 3654 first_arg, lambda cls: cls.is_protocol) 3655 # We should avoid checking the return value against any return annotation 3656 # when we are analyzing an attribute of a protocol or an abstract class's 3657 # abstract method. 3658 check_return = (not (self.is_attribute_of_class and caller_is_protocol) and 3659 not (caller_is_abstract and self.is_abstract)) 3660 if sig.has_return_annotation or not check_return: 3661 frame.allowed_returns = annotations.get( 3662 "return", self.vm.convert.unsolvable) 3663 frame.check_return = check_return 3664 if self.vm.options.skip_repeat_calls: 3665 callkey = abstract_utils.hash_all_dicts( 3666 (callargs, None), 3667 (frame.f_globals.members, set(self.code.co_names)), 3668 (frame.f_locals.members, 3669 set(frame.f_locals.members) - set(self.code.co_varnames))) 3670 else: 3671 # Make the callkey the number of times this function has been called so 3672 # that no call has the same key as a previous one. 3673 callkey = len(self._call_cache) 3674 if callkey in self._call_cache: 3675 old_ret, old_remaining_depth = self._call_cache[callkey] 3676 # Optimization: This function has already been called, with the same 3677 # environment and arguments, so recycle the old return value. 3678 # We would want to skip this optimization and reanalyze the call if we can 3679 # traverse the function deeper. 3680 if self.vm.remaining_depth() > old_remaining_depth: 3681 # TODO(rechen): Reanalysis is necessary only if the VM was unable to 3682 # completely analyze the call with old_remaining_depth. For now, we can 3683 # get away with not checking for completion because of how severely 3684 # --quick constrains the maximum depth. 3685 log.info("Reanalyzing %r because we can traverse deeper; " 3686 "remaining_depth = %d, old_remaining_depth = %d", 3687 self.name, self.vm.remaining_depth(), old_remaining_depth) 3688 else: 3689 ret = old_ret.AssignToNewVariable(node) 3690 if self._store_call_records: 3691 # Even if the call is cached, we might not have been recording it. 3692 self._call_records.append((callargs, ret, node)) 3693 return node, ret 3694 if self.code.has_generator(): 3695 generator = Generator(frame, self.vm) 3696 # Run the generator right now, even though the program didn't call it, 3697 # because we need to know the contained type for futher matching. 3698 node2, _ = generator.run_generator(node) 3699 if self.is_coroutine(): 3700 # This function is a generator-based coroutine. We convert the return 3701 # value here even though byte_GET_AWAITABLE repeats the conversion so 3702 # that matching against a typing.Awaitable annotation succeeds. 3703 # TODO(rechen): PyTDFunction probably also needs to do this. 3704 var = generator.get_instance_type_parameter(abstract_utils.V) 3705 ret = Coroutine(self.vm, var, node2).to_variable(node2) 3706 else: 3707 ret = generator.to_variable(node2) 3708 node_after_call = node2 3709 elif self.code.has_async_generator(): 3710 async_generator = AsyncGenerator(frame, self.vm) 3711 node2, _ = async_generator.run_generator(node) 3712 node_after_call, ret = node2, async_generator.to_variable(node2) 3713 else: 3714 # If any parameters are annotated as Any, we add the annotations to the 3715 # new frame's dictionary of local variable annotations, so that 3716 # vm._apply_annotation will treat these as explicit Any annotations that 3717 # disable inference. 3718 annotated_locals = {} 3719 for name, annot in annotations.items(): 3720 if name != "return" and annot == self.vm.convert.unsolvable: 3721 annotated_locals[name] = abstract_utils.Local( 3722 node, self.get_first_opcode(), annot, callargs.get(name), self.vm) 3723 node2, ret = self.vm.run_frame(frame, node, annotated_locals) 3724 if self.is_coroutine(): 3725 ret = Coroutine(self.vm, ret, node2).to_variable(node2) 3726 node_after_call = node2 3727 self._inner_cls_check(frame) 3728 self._call_cache[callkey] = ret, self.vm.remaining_depth() 3729 if self._store_call_records or self.vm.store_all_calls: 3730 self._call_records.append((callargs, ret, node_after_call)) 3731 self.last_frame = frame 3732 return node_after_call, ret 3733 3734 def get_call_combinations(self, node): 3735 """Get this function's call records.""" 3736 all_combinations = [] 3737 signature_data = set() 3738 for callargs, ret, node_after_call in self._call_records: 3739 try: 3740 combinations = cfg_utils.variable_product_dict(callargs) 3741 except cfg_utils.TooComplexError: 3742 combination = { 3743 name: self.vm.convert.unsolvable.to_binding(node_after_call) 3744 for name in callargs} 3745 combinations = [combination] 3746 ret = self.vm.new_unsolvable(node_after_call) 3747 for combination in combinations: 3748 for return_value in ret.bindings: 3749 values = list(combination.values()) + [return_value] 3750 data = tuple(v.data for v in values) 3751 if data in signature_data: 3752 # This combination yields a signature we already know is possible 3753 continue 3754 # Optimization: when only one combination exists, assume it's visible. 3755 if (len(combinations) == 1 and len(ret.bindings) == 1 or 3756 node_after_call.HasCombination(values)): 3757 signature_data.add(data) 3758 all_combinations.append( 3759 (node_after_call, combination, return_value)) 3760 if not all_combinations: 3761 # Fallback: Generate signatures only from the definition of the 3762 # method, not the way it's being used. 3763 param_binding = self.vm.convert.unsolvable.to_binding(node) 3764 params = collections.defaultdict(lambda: param_binding) 3765 ret = self.vm.convert.unsolvable.to_binding(node) 3766 all_combinations.append((node, params, ret)) 3767 return all_combinations 3768 3769 def get_positional_names(self): 3770 return list(self.code.co_varnames[:self.code.co_argcount]) 3771 3772 def get_nondefault_params(self): 3773 for i in range(self.nonstararg_count): 3774 yield self.code.co_varnames[i], i >= self.code.co_argcount 3775 3776 def get_kwonly_names(self): 3777 return list( 3778 self.code.co_varnames[self.code.co_argcount:self.nonstararg_count]) 3779 3780 def get_parameters(self): 3781 default_pos = self.code.co_argcount - len(self.defaults) 3782 i = 0 3783 for name in self.get_positional_names(): 3784 yield name, False, i >= default_pos 3785 i += 1 3786 for name in self.get_kwonly_names(): 3787 yield name, True, name in self.kw_defaults 3788 i += 1 3789 3790 def has_varargs(self): 3791 return self.code.has_varargs() 3792 3793 def has_kwargs(self): 3794 return self.code.has_varkeywords() 3795 3796 def property_get(self, callself, is_class=False): 3797 if (abstract_utils.func_name_is_class_init(self.name) and 3798 self.signature.param_names): 3799 self_name = self.signature.param_names[0] 3800 # If `_has_self_annot` is True, then we've intentionally temporarily 3801 # annotated `self`; otherwise, a `self` annotation is illegal. 3802 if not self._has_self_annot and self_name in self.signature.annotations: 3803 self.vm.errorlog.invalid_annotation( 3804 self.vm.simple_stack(self.get_first_opcode()), 3805 self.signature.annotations[self_name], 3806 details="Cannot annotate self argument of __init__", name=self_name) 3807 self.signature.del_annotation(self_name) 3808 return super().property_get(callself, is_class) 3809 3810 def is_coroutine(self): 3811 return self.code.has_coroutine() or self.code.has_iterable_coroutine() 3812 3813 def has_empty_body(self): 3814 # TODO(mdemello): Optimise this. 3815 ops = list(self.code.code_iter) 3816 if len(ops) != 2: 3817 # This check isn't strictly necessary but prevents us from wastefully 3818 # building a list of opcode names for a long method. 3819 return False 3820 if [op.name for op in ops] != ["LOAD_CONST", "RETURN_VALUE"]: 3821 return False 3822 return self.code.co_consts[ops[0].arg] is None 3823 3824 3825class SimpleFunction(SignedFunction): 3826 """An abstract value representing a function with a particular signature. 3827 3828 Unlike InterpreterFunction, a SimpleFunction has a set signature and does not 3829 record calls or try to infer types. 3830 """ 3831 3832 def __init__(self, name, param_names, varargs_name, kwonly_params, 3833 kwargs_name, defaults, annotations, vm): 3834 """Create a SimpleFunction. 3835 3836 Args: 3837 name: Name of the function as a string 3838 param_names: Tuple of parameter names as strings. 3839 varargs_name: The "args" in "*args". String or None. 3840 kwonly_params: Tuple of keyword-only parameters as strings. These do NOT 3841 appear in param_names. 3842 kwargs_name: The "kwargs" in "**kwargs". String or None. 3843 defaults: Dictionary of string names to values of default arguments. 3844 annotations: Dictionary of string names to annotations (strings or types). 3845 vm: The virtual machine for this function. 3846 """ 3847 annotations = dict(annotations) 3848 # Every parameter must have an annotation. Defaults to unsolvable. 3849 for n in itertools.chain(param_names, [varargs_name, kwargs_name], 3850 kwonly_params): 3851 if n and n not in annotations: 3852 annotations[n] = vm.convert.unsolvable 3853 if not isinstance(defaults, dict): 3854 defaults = dict(zip(param_names[-len(defaults):], defaults)) 3855 signature = function.Signature(name, param_names, varargs_name, 3856 kwonly_params, kwargs_name, defaults, 3857 annotations) 3858 super().__init__(signature, vm) 3859 self.bound_class = BoundFunction 3860 3861 @classmethod 3862 def from_signature(cls, signature, vm): 3863 """Create a SimpleFunction from a function.Signature.""" 3864 return cls( 3865 name=signature.name, 3866 param_names=signature.param_names, 3867 varargs_name=signature.varargs_name, 3868 kwonly_params=signature.kwonly_params, 3869 kwargs_name=signature.kwargs_name, 3870 defaults=signature.defaults, 3871 annotations=signature.annotations, 3872 vm=vm) 3873 3874 def call(self, node, _, args, alias_map=None): 3875 # We only simplify args for _map_args, because that simplifies checking. 3876 # This allows match_args to typecheck varargs and kwargs. 3877 callargs = self._map_args(node, args.simplify(node, self.vm)) 3878 substs = self.match_args(node, args, alias_map) 3879 # Substitute type parameters in the signature's annotations. 3880 annotations = self.vm.annotations_util.sub_annotations( 3881 node, self.signature.annotations, substs, instantiate_unbound=False) 3882 if self.signature.has_return_annotation: 3883 ret_type = annotations["return"] 3884 ret = ret_type.instantiate(node) 3885 else: 3886 ret = self.vm.convert.none.to_variable(node) 3887 if self.name == "__new__": 3888 self_arg = ret 3889 else: 3890 self_arg = self.signature.get_first_arg(callargs) 3891 mutations = self._mutations_generator(node, self_arg, substs) 3892 node = abstract_utils.apply_mutations(node, mutations) 3893 return node, ret 3894 3895 3896class BoundFunction(BaseValue): 3897 """An function type which has had an argument bound into it.""" 3898 3899 def __init__(self, callself, underlying): 3900 super().__init__(underlying.name, underlying.vm) 3901 self._callself = callself 3902 self.underlying = underlying 3903 self.is_attribute_of_class = False 3904 self.is_class_builder = False 3905 3906 # If the function belongs to `ParameterizedClass`, we will annotate the 3907 # `self` when do argument matching 3908 self.replace_self_annot = None 3909 inst = abstract_utils.get_atomic_value( 3910 self._callself, default=self.vm.convert.unsolvable) 3911 if self._should_replace_self_annot(): 3912 if isinstance(inst.cls, class_mixin.Class): 3913 for cls in inst.cls.mro: 3914 if isinstance(cls, ParameterizedClass): 3915 base_cls = cls.base_cls 3916 else: 3917 base_cls = cls 3918 if isinstance(base_cls, class_mixin.Class) and base_cls.template: 3919 self.replace_self_annot = ( 3920 ParameterizedClass.get_generic_instance_type(base_cls)) 3921 break 3922 if isinstance(inst, SimpleValue): 3923 self.alias_map = inst.instance_type_parameters.uf 3924 elif isinstance(inst, TypeParameterInstance): 3925 self.alias_map = inst.instance.instance_type_parameters.uf 3926 else: 3927 self.alias_map = None 3928 3929 def _should_replace_self_annot(self): 3930 # To do argument matching for custom generic classes, the 'self' annotation 3931 # needs to be replaced with a generic type. 3932 f = self.underlying 3933 if not isinstance(f, SignedFunction) or not f.signature.param_names: 3934 # no 'self' to replace 3935 return False 3936 if isinstance(f, InterpreterFunction): 3937 # always replace for user-defined methods 3938 return True 3939 # SimpleFunctions are methods we construct internally for generated classes 3940 # like namedtuples. 3941 if not isinstance(f, SimpleFunction): 3942 return False 3943 # We don't want to clobber our own generic annotations. 3944 return (f.signature.param_names[0] not in f.signature.annotations or 3945 not f.signature.annotations[f.signature.param_names[0]].formal) 3946 3947 def argcount(self, node): 3948 return self.underlying.argcount(node) - 1 # account for self 3949 3950 @property 3951 def signature(self): 3952 return self.underlying.signature.drop_first_parameter() 3953 3954 @property 3955 def callself(self): 3956 return self._callself 3957 3958 def call(self, node, func, args, alias_map=None): 3959 if abstract_utils.func_name_is_class_init(self.name): 3960 self.vm.callself_stack.append(self._callself) 3961 # The "self" parameter is automatically added to the list of arguments, but 3962 # only if the function actually takes any arguments. 3963 if self.argcount(node) >= 0: 3964 args = args.replace(posargs=(self._callself,) + args.posargs) 3965 try: 3966 if self.replace_self_annot: 3967 with self.underlying.set_self_annot(self.replace_self_annot): 3968 node, ret = self.underlying.call(node, func, args, 3969 alias_map=self.alias_map) 3970 else: 3971 node, ret = self.underlying.call(node, func, args, 3972 alias_map=self.alias_map) 3973 except function.InvalidParameters as e: 3974 if self._callself and self._callself.bindings: 3975 if "." in e.name: 3976 # match_args will try to prepend the parent's name to the error name. 3977 # Overwrite it with _callself instead, which may be more exact. 3978 _, _, e.name = e.name.rpartition(".") 3979 e.name = "%s.%s" % (self._callself.data[0].name, e.name) 3980 raise 3981 finally: 3982 if abstract_utils.func_name_is_class_init(self.name): 3983 self.vm.callself_stack.pop() 3984 return node, ret 3985 3986 def get_positional_names(self): 3987 return self.underlying.get_positional_names() 3988 3989 def has_varargs(self): 3990 return self.underlying.has_varargs() 3991 3992 def has_kwargs(self): 3993 return self.underlying.has_kwargs() 3994 3995 def get_class(self): 3996 return self.underlying.get_class() 3997 3998 @property 3999 def is_abstract(self): 4000 return self.underlying.is_abstract 4001 4002 @is_abstract.setter 4003 def is_abstract(self, value): 4004 self.underlying.is_abstract = value 4005 4006 @property 4007 def is_classmethod(self): 4008 return self.underlying.is_classmethod 4009 4010 def repr_names(self, callself_repr=None): 4011 """Names to use in the bound function's string representation. 4012 4013 This function can return multiple names because there may be multiple 4014 bindings in callself. 4015 4016 Args: 4017 callself_repr: Optionally, a repr function for callself. 4018 4019 Returns: 4020 A non-empty iterable of string names. 4021 """ 4022 callself_repr = callself_repr or (lambda v: v.name) 4023 if self._callself and self._callself.bindings: 4024 callself_names = [callself_repr(v) for v in self._callself.data] 4025 else: 4026 callself_names = ["<class>"] 4027 # We don't need to recursively call repr_names() because we replace the 4028 # parent name with the callself. 4029 underlying = self.underlying.name 4030 if underlying.count(".") > 0: 4031 underlying = underlying.split(".", 1)[-1] 4032 return [callself + "." + underlying for callself in callself_names] 4033 4034 def __repr__(self): 4035 return self.repr_names()[0] + "(...)" 4036 4037 4038class BoundInterpreterFunction(BoundFunction): 4039 """The method flavor of InterpreterFunction.""" 4040 4041 @contextlib.contextmanager 4042 def record_calls(self): 4043 with self.underlying.record_calls(): 4044 yield 4045 4046 def get_first_opcode(self): 4047 return self.underlying.code.first_opcode 4048 4049 @property 4050 def has_overloads(self): 4051 return self.underlying.has_overloads 4052 4053 @property 4054 def is_overload(self): 4055 return self.underlying.is_overload 4056 4057 @is_overload.setter 4058 def is_overload(self, value): 4059 self.underlying.is_overload = value 4060 4061 @property 4062 def defaults(self): 4063 return self.underlying.defaults 4064 4065 def iter_signature_functions(self): 4066 for f in self.underlying.iter_signature_functions(): 4067 yield self.underlying.bound_class(self._callself, f) 4068 4069 4070class BoundPyTDFunction(BoundFunction): 4071 pass 4072 4073 4074class Coroutine(Instance): 4075 """A representation of instances of coroutine.""" 4076 4077 def __init__(self, vm, ret_var, node): 4078 super().__init__(vm.convert.coroutine_type, vm) 4079 self.merge_instance_type_parameter( 4080 node, abstract_utils.T, self.vm.new_unsolvable(node)) 4081 self.merge_instance_type_parameter( 4082 node, abstract_utils.T2, self.vm.new_unsolvable(node)) 4083 self.merge_instance_type_parameter( 4084 node, abstract_utils.V, ret_var.AssignToNewVariable(node)) 4085 4086 @classmethod 4087 def make(cls, vm, func, node): 4088 """Get return type of coroutine function.""" 4089 assert func.signature.has_return_annotation 4090 ret_val = func.signature.annotations["return"] 4091 if func.code.has_coroutine(): 4092 ret_var = ret_val.instantiate(node) 4093 elif func.code.has_iterable_coroutine(): 4094 ret_var = ret_val.get_formal_type_parameter( 4095 abstract_utils.V).instantiate(node) 4096 return cls(vm, ret_var, node) 4097 4098 4099class BaseGenerator(Instance): 4100 """A base class of instances of generators and async generators.""" 4101 4102 def __init__(self, generator_type, frame, vm, is_return_allowed): 4103 super().__init__(generator_type, vm) 4104 self.frame = frame 4105 self.runs = 0 4106 self.is_return_allowed = is_return_allowed # if return statement is allowed 4107 4108 def run_generator(self, node): 4109 """Run the generator.""" 4110 if self.runs == 0: # Optimization: We only run it once. 4111 node, _ = self.vm.resume_frame(node, self.frame) 4112 ret_type = self.frame.allowed_returns 4113 if ret_type: 4114 # set type parameters according to annotated Generator return type 4115 type_params = [abstract_utils.T, abstract_utils.T2] 4116 if self.is_return_allowed: 4117 type_params.append(abstract_utils.V) 4118 for param_name in type_params: 4119 _, param_var = self.vm.init_class( 4120 node, ret_type.get_formal_type_parameter(param_name)) 4121 self.merge_instance_type_parameter(node, param_name, param_var) 4122 else: 4123 # infer the type parameters based on the collected type information. 4124 self.merge_instance_type_parameter( 4125 node, abstract_utils.T, self.frame.yield_variable) 4126 # For T2 type, it can not be decided until the send/asend function is 4127 # called later on. So set T2 type as ANY so that the type check will 4128 # not fail when the function is called afterwards. 4129 self.merge_instance_type_parameter( 4130 node, abstract_utils.T2, 4131 self.vm.new_unsolvable(node)) 4132 if self.is_return_allowed: 4133 self.merge_instance_type_parameter( 4134 node, abstract_utils.V, self.frame.return_variable) 4135 self.runs += 1 4136 return node, self.get_instance_type_parameter(abstract_utils.T) 4137 4138 def call(self, node, func, args, alias_map=None): 4139 """Call this generator or (more common) its "next/anext" attribute.""" 4140 del func, args 4141 return self.run_generator(node) 4142 4143 4144class Generator(BaseGenerator): 4145 """A representation of instances of generators.""" 4146 4147 def __init__(self, generator_frame, vm): 4148 super().__init__(vm.convert.generator_type, generator_frame, vm, True) 4149 4150 def get_special_attribute(self, node, name, valself): 4151 if name == "__iter__": 4152 f = NativeFunction(name, self.__iter__, self.vm) 4153 return f.to_variable(node) 4154 elif name == self.vm.convert.next_attr: 4155 return self.to_variable(node) 4156 elif name == "throw": 4157 # We don't model exceptions in a way that would allow us to induce one 4158 # inside a coroutine. So just return ourself, mapping the call of 4159 # throw() to a next() (which won't be executed). 4160 return self.to_variable(node) 4161 else: 4162 return super().get_special_attribute(node, name, valself) 4163 4164 def __iter__(self, node): # pylint: disable=non-iterator-returned,unexpected-special-method-signature 4165 return node, self.to_variable(node) 4166 4167 4168class AsyncGenerator(BaseGenerator): 4169 """A representation of instances of async generators.""" 4170 4171 def __init__(self, async_generator_frame, vm): 4172 super().__init__(vm.convert.async_generator_type, async_generator_frame, vm, 4173 False) 4174 4175 4176class Iterator(Instance, mixin.HasSlots): 4177 """A representation of instances of iterators.""" 4178 4179 def __init__(self, vm, return_var): 4180 super().__init__(vm.convert.iterator_type, vm) 4181 mixin.HasSlots.init_mixin(self) 4182 self.set_slot(self.vm.convert.next_attr, self.next_slot) 4183 # TODO(dbaum): Should we set instance_type_parameters[self.TYPE_PARAM] to 4184 # something based on return_var? 4185 self._return_var = return_var 4186 4187 def next_slot(self, node): 4188 return node, self._return_var 4189 4190 4191class Splat(BaseValue): 4192 """Representation of unpacked iterables.""" 4193 4194 def __init__(self, vm, iterable): 4195 super().__init__("splat", vm) 4196 self.iterable = iterable 4197 4198 def get_class(self): 4199 # When building a tuple for a function call, we preserve splats as elements 4200 # in a concrete tuple (e.g. f(x, *ys, z) gets called with the concrete tuple 4201 # (x, *ys, z) in starargs) and let the arg matcher in function.py unpack 4202 # them. Constructing the tuple invokes get_class() as a side effect; ideally 4203 # we would specialise abstract.Tuple for function calls and not bother 4204 # constructing an associated TupleClass for a function call tuple, but for 4205 # now we just set the class to Any here. 4206 return self.vm.convert.unsolvable 4207 4208 def __repr__(self): 4209 return "splat(%r)" % self.iterable.data 4210 4211 4212class Module(Instance, mixin.LazyMembers): 4213 """Represents an (imported) module.""" 4214 4215 def __init__(self, vm, name, member_map, ast): 4216 super().__init__(vm.convert.module_type, vm) 4217 self.name = name 4218 self.ast = ast 4219 mixin.LazyMembers.init_mixin(self, member_map) 4220 4221 def _convert_member(self, member, subst=None): 4222 """Called to convert the items in _member_map to cfg.Variable.""" 4223 var = self.vm.convert.constant_to_var(member) 4224 for value in var.data: 4225 # Only do this if this is a class which isn't already part of a module, or 4226 # is a module itself. 4227 # (This happens if e.g. foo.py does "from bar import x" and we then 4228 # do "from foo import x".) 4229 if not value.module and not isinstance(value, Module): 4230 value.module = self.name 4231 return var 4232 4233 @property 4234 def module(self): 4235 return None 4236 4237 @module.setter 4238 def module(self, m): 4239 assert (m is None or m == self.ast.name), (m, self.ast.name) 4240 4241 @property 4242 def full_name(self): 4243 return self.ast.name 4244 4245 def has_getattr(self): 4246 """Does this module have a module-level __getattr__? 4247 4248 We allow __getattr__ on the module level to specify that this module doesn't 4249 have any contents. The typical syntax is 4250 def __getattr__(name) -> Any 4251 . 4252 See https://www.python.org/dev/peps/pep-0484/#stub-files 4253 4254 Returns: 4255 True if we have __getattr__. 4256 """ 4257 f = self._member_map.get("__getattr__") 4258 if f: 4259 if isinstance(f, pytd.Function): 4260 if len(f.signatures) != 1: 4261 log.warning("overloaded module-level __getattr__ (in %s)", self.name) 4262 elif f.signatures[0].return_type != pytd.AnythingType(): 4263 log.warning("module-level __getattr__ doesn't return Any (in %s)", 4264 self.name) 4265 return True 4266 else: 4267 log.warning("__getattr__ in %s is not a function", self.name) 4268 return False 4269 4270 def get_submodule(self, node, name): 4271 full_name = self.name + "." + name 4272 mod = self.vm.import_module(full_name, full_name, 0) # 0: absolute import 4273 if mod is not None: 4274 return mod.to_variable(node) 4275 elif self.has_getattr(): 4276 return self.vm.new_unsolvable(node) 4277 else: 4278 log.warning("Couldn't find attribute / module %r", full_name) 4279 return None 4280 4281 def items(self): 4282 for name in self._member_map: 4283 self.load_lazy_attribute(name) 4284 return list(self.members.items()) 4285 4286 def get_fullhash(self): 4287 """Hash the set of member names.""" 4288 m = hashlib.md5() 4289 m.update(self.full_name.encode("utf-8")) 4290 for k in self._member_map: 4291 m.update(k.encode("utf-8")) 4292 return m.digest() 4293 4294 4295class BuildClass(BaseValue): 4296 """Representation of the Python 3 __build_class__ object.""" 4297 4298 CLOSURE_NAME = "__class__" 4299 4300 def __init__(self, vm): 4301 super().__init__("__build_class__", vm) 4302 4303 def call(self, node, _, args, alias_map=None): 4304 args = args.simplify(node, self.vm) 4305 funcvar, name = args.posargs[0:2] 4306 if isinstance(args.namedargs, dict): 4307 kwargs = args.namedargs 4308 else: 4309 kwargs = self.vm.convert.value_to_constant(args.namedargs, dict) 4310 # TODO(mdemello): Check if there are any changes between python2 and 4311 # python3 in the final metaclass computation. 4312 # TODO(b/123450483): Any remaining kwargs need to be passed to the 4313 # metaclass. 4314 metaclass = kwargs.get("metaclass", None) 4315 if len(funcvar.bindings) != 1: 4316 raise abstract_utils.ConversionError( 4317 "Invalid ambiguous argument to __build_class__") 4318 func, = funcvar.data 4319 if not isinstance(func, InterpreterFunction): 4320 raise abstract_utils.ConversionError( 4321 "Invalid argument to __build_class__") 4322 func.is_class_builder = True 4323 bases = args.posargs[2:] 4324 subst = {} 4325 # We need placeholder values to stick in 'subst'. These will be replaced by 4326 # the actual type parameter values when attribute.py looks up generic 4327 # attributes on instances of this class. 4328 any_var = self.vm.new_unsolvable(node) 4329 for basevar in bases: 4330 for base in basevar.data: 4331 if isinstance(base, ParameterizedClass): 4332 subst.update( 4333 {v.name: any_var for v in base.formal_type_parameters.values() 4334 if isinstance(v, TypeParameter)}) 4335 4336 node, _ = func.call(node, funcvar.bindings[0], 4337 args.replace(posargs=(), namedargs={}), 4338 new_locals=True, frame_substs=(subst,)) 4339 if func.last_frame: 4340 func.f_locals = func.last_frame.f_locals 4341 class_closure_var = func.last_frame.class_closure_var 4342 else: 4343 # We have hit 'maximum depth' before setting func.last_frame 4344 func.f_locals = self.vm.convert.unsolvable 4345 class_closure_var = None 4346 for base in bases: 4347 # If base class is NamedTuple, we will call its own make_class method to 4348 # make a class. 4349 base = abstract_utils.get_atomic_value( 4350 base, default=self.vm.convert.unsolvable) 4351 cls_dict = func.f_locals.to_variable(node) 4352 # Every subclass of an enum is itself an enum. To properly process them, 4353 # the class must be built by the enum overlay. 4354 if (base.isinstance_Class() and base.is_enum and 4355 self.vm.options.use_enum_overlay): 4356 enum_base = abstract_utils.get_atomic_value( 4357 self.vm.loaded_overlays["enum"].members["Enum"]) 4358 return enum_base.make_class( 4359 node, name, list(bases), cls_dict, metaclass, 4360 new_class_var=class_closure_var, is_decorated=self.is_decorated) 4361 if isinstance(base, PyTDClass) and base.full_name == "typing.NamedTuple": 4362 # The subclass of NamedTuple will ignore all its base classes. This is 4363 # controled by a metaclass provided to NamedTuple. 4364 return base.make_class(node, list(bases), cls_dict) 4365 return self.vm.make_class( 4366 node, name, list(bases), func.f_locals.to_variable(node), metaclass, 4367 new_class_var=class_closure_var, is_decorated=self.is_decorated) 4368 4369 4370class Unsolvable(Singleton): 4371 """Representation of value we know nothing about. 4372 4373 Unlike "Unknowns", we don't treat these as solveable. We just put them 4374 where values are needed, but make no effort to later try to map them 4375 to named types. This helps conserve memory where creating and solving 4376 hundreds of unknowns would yield us little to no information. 4377 4378 This is typically a singleton. Since unsolvables are indistinguishable, we 4379 only need one. 4380 """ 4381 IGNORED_ATTRIBUTES = ["__get__", "__set__", "__getattribute__"] 4382 4383 # Since an unsolvable gets generated e.g. for every unresolved import, we 4384 # can have multiple circular Unsolvables in a class' MRO. Treat those special. 4385 SINGLETON = True 4386 4387 def __init__(self, vm): 4388 super().__init__("unsolveable", vm) 4389 4390 def get_special_attribute(self, node, name, _): 4391 # Overrides Singleton.get_special_attributes. 4392 if name in self.IGNORED_ATTRIBUTES: 4393 return None 4394 else: 4395 return self.to_variable(node) 4396 4397 def argcount(self, _): 4398 return 0 4399 4400 4401class Unknown(BaseValue): 4402 """Representation of unknown values. 4403 4404 These are e.g. the return values of certain functions (e.g. eval()). They 4405 "adapt": E.g. they'll respond to get_attribute requests by creating that 4406 attribute. 4407 4408 Attributes: 4409 members: Attributes that were written or read so far. Mapping of str to 4410 cfg.Variable. 4411 owner: cfg.Binding that contains this instance as data. 4412 """ 4413 4414 _current_id = 0 4415 4416 # For simplicity, Unknown doesn't emulate descriptors: 4417 IGNORED_ATTRIBUTES = ["__get__", "__set__", "__getattribute__"] 4418 4419 def __init__(self, vm): 4420 name = escape.unknown(Unknown._current_id) 4421 super().__init__(name, vm) 4422 self.members = datatypes.MonitorDict() 4423 self.owner = None 4424 Unknown._current_id += 1 4425 self.class_name = self.name 4426 self._calls = [] 4427 log.info("Creating %s", self.class_name) 4428 4429 def compute_mro(self): 4430 return self.default_mro() 4431 4432 def get_fullhash(self): 4433 # Unknown needs its own implementation of get_fullhash to ensure equivalent 4434 # Unknowns produce the same hash. "Equivalent" in this case means "has the 4435 # same members," so member names are used in the hash instead of id(). 4436 m = hashlib.md5() 4437 for name in self.members: 4438 m.update(name.encode("utf-8")) 4439 return m.digest() 4440 4441 def get_children_maps(self): 4442 return (self.members,) 4443 4444 @classmethod 4445 def _to_pytd(cls, node, v): 4446 if isinstance(v, cfg.Variable): 4447 return pytd_utils.JoinTypes(cls._to_pytd(node, t) for t in v.data) 4448 elif isinstance(v, Unknown): 4449 # Do this directly, and use NamedType, in case there's a circular 4450 # dependency among the Unknown instances. 4451 return pytd.NamedType(v.class_name) 4452 else: 4453 return v.to_type(node) 4454 4455 @classmethod 4456 def _make_params(cls, node, args): 4457 """Convert a list of types/variables to pytd parameters.""" 4458 def _make_param(i, p): 4459 return pytd.Parameter("_%d" % (i + 1), cls._to_pytd(node, p), 4460 kwonly=False, optional=False, mutated_type=None) 4461 return tuple(_make_param(i, p) for i, p in enumerate(args)) 4462 4463 def get_special_attribute(self, node, name, valself): 4464 del node, valself 4465 if name in self.IGNORED_ATTRIBUTES: 4466 return None 4467 if name in self.members: 4468 return self.members[name] 4469 new = self.vm.convert.create_new_unknown( 4470 self.vm.root_node, action="getattr_" + self.name + ":" + name) 4471 # We store this at the root node, even though we only just created this. 4472 # From the analyzing point of view, we don't know when the "real" version 4473 # of this attribute (the one that's not an unknown) gets created, hence 4474 # we assume it's there since the program start. If something overwrites it 4475 # in some later CFG node, that's fine, we'll then work only with the new 4476 # value, which is more accurate than the "fictional" value we create here. 4477 self.vm.attribute_handler.set_attribute(self.vm.root_node, self, name, new) 4478 return new 4479 4480 def call(self, node, _, args, alias_map=None): 4481 ret = self.vm.convert.create_new_unknown( 4482 node, source=self.owner, action="call:" + self.name) 4483 self._calls.append((args.posargs, args.namedargs, ret)) 4484 return node, ret 4485 4486 def argcount(self, _): 4487 return 0 4488 4489 def to_variable(self, node): 4490 v = self.vm.program.NewVariable() 4491 val = v.AddBinding(self, source_set=[], where=node) 4492 self.owner = val 4493 self.vm.trace_unknown(self.class_name, val) 4494 return v 4495 4496 def to_structural_def(self, node, class_name): 4497 """Convert this Unknown to a pytd.Class.""" 4498 self_param = (pytd.Parameter("self", pytd.AnythingType(), 4499 False, False, None),) 4500 starargs = None 4501 starstarargs = None 4502 def _make_sig(args, ret): 4503 return pytd.Signature(self_param + self._make_params(node, args), 4504 starargs, 4505 starstarargs, 4506 return_type=Unknown._to_pytd(node, ret), 4507 exceptions=(), 4508 template=()) 4509 calls = tuple(pytd_utils.OrderedSet( 4510 _make_sig(args, ret) for args, _, ret in self._calls)) 4511 if calls: 4512 methods = (pytd.Function("__call__", calls, pytd.MethodTypes.METHOD),) 4513 else: 4514 methods = () 4515 # TODO(rechen): Should we convert self.cls to a metaclass here as well? 4516 return pytd.Class( 4517 name=class_name, 4518 metaclass=None, 4519 parents=(pytd.NamedType("builtins.object"),), 4520 methods=methods, 4521 constants=tuple(pytd.Constant(name, Unknown._to_pytd(node, c)) 4522 for name, c in self.members.items()), 4523 classes=(), 4524 decorators=(), 4525 slots=None, 4526 template=()) 4527 4528 def get_class(self): 4529 # We treat instances of an Unknown as the same as the class. 4530 return self 4531 4532 def instantiate(self, node, container=None): 4533 return self.to_variable(node) 4534 4535 4536AMBIGUOUS = (Unknown, Unsolvable) 4537AMBIGUOUS_OR_EMPTY = AMBIGUOUS + (Empty,) 4538FUNCTION_TYPES = (BoundFunction, Function) 4539INTERPRETER_FUNCTION_TYPES = (BoundInterpreterFunction, InterpreterFunction) 4540PYTD_FUNCTION_TYPES = (BoundPyTDFunction, PyTDFunction) 4541