Skip to content

Assignment of Any does not get rid of Optional (add AnyUnion type?) #3526

@ddfisher

Description

@ddfisher

Consider this code (run with --strict-optional):

from typing import Optional
def f():
  # untyped function; often from silent import
  return 0  # always returns an int

def g(x: Optional[int]) -> int
  if x is None:
    x = f()
  return x  # E: Incompatible return value type (got "Optional[int]", expected "int")

Mypy doesn't infer that x is not None in g. I think this a bug -- mypy
should be permissive here.

If we wanted to fix this, we'd run into a problem: what type should x have
after x = f()? We don't want it to be Any, because we don't want that
behavior in the general case. It shouldn't be int -- f() could be intended
to unconditionally return None instead. To fix this, I think we need to
introduce a new special type, which I will call AnyUnion. AnyUnion[A, B, C] would represent a type which is allowed to be used as any of A, B, or
C (similarly to how Any is allowed to be used as any type). In this case,
we could have x's type bound to AnyUnion[int, None], which would fix this
error.

Other helpful uses of AnyUnion:

  • pow will no longer need to return Any in builtins. Instead, it could
    return the much less broad AnyUnion[int, float].
  • AnyUnion[X, None] would provide a per-variable opt-out of strict None
    checking. This could be helpful for classes with delayed initialization where
    a lot of effort would be needed to refactor them into a state that would work
    properly with strict None checking.

Cons:

  • Additional complexity of the type system affects implementation complexity and
    makes things slightly harder for users to understand.
  • The motivating problem also exists with subclasses (with the way the binder
    currently works), but AnyUnion doesn't help much with that.

Metadata

Metadata

Assignees

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions