Skip to content

Do not type check modules that don't import typing #186

Closed

Description

@JukkaL

If a module does not import typing, it should not be type checked. Currently all
modules are type checked (except for dynamically typed functions).

Activity

  1. JukkaL commented on Dec 29, 2014

    @JukkaL
    CollaboratorAuthor

    Also, modules that don't import typing should have more lenient semantic analysis -- or maybe even we shouldn't report any errors for those. Some ideas below (these would only apply to modules that don't import typing):

    Don't complain about missing modules/stubs

    Just define all names imported from unknown modules with implicit type Any. For example:

    import nonexistent
    from nonexistent2 import x
    # both nonexistent and x have type Any

    All variables have implicit type Any

    This includes names imported from statically typed modules. For imported functions we should just erase the signature (replace argument / return value types with Any) if we want to be fancy (but see below). We should not erase the types of names that refer to modules or classes.

    In the first version it's okay to always retain the types of imported names if this simplifies the implementation.

    All functions have implicit type signature with Any types

    However, we should keep track of the number and kinds of arguments, and their names.

    Infer structure of classes

    We should keep track of the structure of any classes, but all attributes/functions behave as above. This way we can use classes defined in dynamically typed modules as types and check method argument counts, etc.

    All classes dynamic?

    All classes defined in dynamically typed modules could be open/dynamic, i.e. any attribute references targeting the class object or a class instance are accepted. Not sure about this, though, since it restricts type checking effectiveness.

    For example, consider this dynamically typed module:

    # m.py
    class A: 
        def bar(self): pass

    Now this module should only have one error, if we have implicit dynamic classes:

    import typing  # this module is statically typed!
    import m
    
    def f(x: m.A) -> None: 
        x.foo()   # okay, since A is open and foo is not defined in A
        x.bar(1)  # error, since bar takes no arguments
        x.bar = 1   # also okay

    Deal with multiple definitions

    If a definition has multiple conflicting definitions (such as a conditionally defined function defined with conflicting argument counts) we should optimally fall back to Any or a suitable, less specific type that covers all the possible definitions. This is for extra credit and can be solved in a separate issue. The simplest approach (which is still okay) is to just pick the first definition and ignore any further definitions.

    Hypothetical example:

    if WINDOWS:
        def make_file(name): ...
    else:
        def make_file(name, perm='rw'): ...

    It's okay if the signature of make_file is inferred to have just a single argument, but it would be better if we'd pick the second definition, since it's more general.

  2. JukkaL commented on Mar 29, 2015

    @JukkaL
    CollaboratorAuthor

    This is probably not how PEP 484 does it, so we might not actually implement this.

  3. JukkaL commented on May 17, 2015

    @JukkaL
    CollaboratorAuthor

    Closing this as not compliant with PEP 484.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions