Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ghost opened this issue Sep 16, 2015 · 8 comments
Closed

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

ghost opened this issue Sep 16, 2015 · 8 comments
Labels

Comments

@ghost
Copy link

ghost commented Sep 16, 2015

I would like something like this to be an error:

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

NYKevin commented Sep 22, 2015

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.

@ghost
Copy link
Author

ghost commented Sep 24, 2015

That's great. Hopefully a dupe with a fix already in the works 👍 Does that mean mypy will get exhaustive checks on unions for free?

def f(x: Union[int, str]) -> int:
  if isinstance(x, int):
    return x + 1
  // not exhaustive: str not checked, so missing branch -> None -> type error?

Also, will pass get special treatment vis-a-vis this None issue, perhaps as type Any? Will all pass be treated the same or just some?

def stub(x: int) -> int:
  pass

vs.

def stub(x: int) -> int:  // intentional stub, but I still want to type-check usages
  if x > 3:
    return x + 1
  else:
    pass

@o11c
Copy link
Contributor

o11c commented Sep 24, 2015

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

@NYKevin
Copy link

NYKevin commented Sep 24, 2015

@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.

@JukkaL
Copy link
Collaborator

JukkaL commented Oct 1, 2015

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.

@JukkaL
Copy link
Collaborator

JukkaL commented Oct 1, 2015

Closing as dupe.

@desmond-dsouza
Copy link

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.

@rwbarton
Copy link
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
Labels
Projects
None yet
Development

No branches or pull requests

5 participants