google / pytype

A static type analyzer for Python code
https://google.github.io/pytype
Other
4.78k stars 279 forks source link

Not checking all possible parameter types for function calls #365

Open gpshead opened 5 years ago

gpshead commented 5 years ago

Take this example code, I was hoping pytype would flag the bug of blindly using an & on the result of an Optional[int] function without checking for None. It unfortunately allows it.

"""pytype allows & on an Optional[int] result.  Why?"""
import sys
from typing import Optional

class Bar:
  def getter(self, param: str) -> Optional[int]:
    if 'a' in param:
      return 0x1111
    return None

class Foo:
  def __init__(self, bar: Bar):
    self._bar = bar

  def action(self, param) -> str:
    optional_int = self._bar.getter(param)
    if optional_int & 0xcafe:
      return 'cafe bits'
    return 'other'

def main(argv):
  if len(argv) > 1:
    param = argv[1]
  else:
    param = 'no-eh'
  foo = Foo(bar=Bar())
  print(foo.action(param))

if __name__ == '__main__':
  main(sys.argv)

(aka experimental/users/gps/pytype/optional_int_binop.py internally)

I expect this can be simplified further, I started by recreating a similar (though already simpler) structure to pytype checked code I was fixing an actual bug in.

rchen152 commented 5 years ago

This looks like https://google.github.io/pytype/faq.html#why-didnt-pytype-catch-that-my-program-might-pass-an-invalid-argument-to-a-function. When a function is passed an argument with multiple possible types, pytype allows it as long as one of the types is valid =/

cebtenzzre commented 2 years ago

I know --strict-parameter-checks is experimental, but for what it's worth, this is the reason I stopped using it:

x = {0: '1', 'a': 'b'}
print(x[0])
$ pytype-single --strict-parameter-checks repr.py
File "repr.py", line 2, in <module>: unsupported operand type(s) for item retrieval: Dict[Union[int, str], str] and int [unsupported-operands]
  Function __getitem__ on Dict[Union[int, str], str] expects str

For more details, see https://google.github.io/pytype/errors.html#unsupported-operands

edit: This seems to have been fixed.