Skip to content

Any option to not allow None as valid member of every type? #875

Closed

Description

I would like something like this to be an error:

def f(i: int) -> int:
    if i > 3:
        return i + 2
    else:
        return None

Activity

  1. NYKevin commented on Sep 22, 2015

    @NYKevin

    This is supposed to be an error unless you use Optional[int] (or Union[int, None]), according to PEP 484. I was under the impression this was a known bug, but I can't find anything to dupe it against.

  2. o11c commented on Sep 24, 2015

    @o11c
    Contributor

    I think you're supposed to use ... instead of pass to indicate a deliberate stub.

  3. NYKevin commented on Sep 24, 2015

    @NYKevin

    @Dedolg: None of those examples are legal under PEP 484, which does not appear to special case pass. You said you would return int. You actually returned None in some (or all) code paths. So you broke the rules. You would have to return Optional[int] for those to be legal, in which case you presumably don't get any checking of exhaustiveness.

    You could also do this in a stub (.pyi) file:

    def stub(x: int) -> int:
        ...
    @typing.overload
    def stub(x: str) -> None:
        ...
    

    Then the int path has to return int and the str path must return None. Verifying that statically may not be possible in every situation, but it is the contract you are promising to abide by. The type checker could use this information to lint other things which call stub().

    No idea how much of this stuff is actually implemented by mypy, though.

  4. JukkaL commented on Oct 1, 2015

    @JukkaL
    Collaborator

    This is a duplicate of #359 and the original issue has additional discussion, though some of it is now out of date. This would be a great thing to have, and I've been looking at this question for a long time -- but we haven't made a ton of progress yet.

    At least these things are blocking this:

    1. We need better type inference for conditional type checks (or boolean checks for None values). Type of variable after isinstance check with 'and' #473, assert and isinstance type inference #475 and Type inference with 'not isinstance' checks #476 are some examples, but there might be others (all of which would be generalized for None checks).
    2. We need to annotate stubs to use Optional[...] everywhere where None is valid (unless None is a default argument value, in which case Optional[...] is implicit).
    3. We should experiment with lots of real-world code to see whether None type checking is powerful enough and doesn't generate too many false positives.
    4. We need to figure out what to do with functions with pass bodies that can't return None. Should we just reject them?

    Together this is probably at least a few weeks of work. We could postpone 2 and 3 and initially have a flag to optionally enable explicit None checking, but the default would be the current behavior until we have confidence that mypy does a good enough job. I'm fine with introducing the flag right now, even though type inference is probably a bit too limited.

    Further discussion should be moved to #359 or individual, more specific issues.

  5. JukkaL commented on Oct 1, 2015

    @JukkaL
    Collaborator

    Closing as dupe.

  6. desmond-dsouza commented on Dec 2, 2015

    @desmond-dsouza

    I think the option of introducing the flag option for None checking right now would be a great first step, and could provide quite useful usage info for all 4 items above.

  7. rwbarton commented on Jun 23, 2016

    @rwbarton
    Contributor

    The flag --strict-optional now exists, though points 2, 3 and 4 from Jukka's comment above are still in progress.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions