Closed
Description
Sometimes it is useful to narrow down a type after an in
/not in
comparison. For example:
class Option:
...
opt: Union[Option, str]
if opt in ('verbose', 'silent'):
reveal_type(opt) # we know this is 'str'
else:
... # still a union here
presets: List[Option]
if opt not in presets:
... # still a union
else:
reveal_type(opt) # we know this can be only 'Option'
This seems to be especially useful for --strict-optional
, for example:
class Node:
fullname: Optional[str]
n: Node
reverse_aliases: Dict[str, str]
if n.fullname in reverse_aliases:
reveal_type(n.fullname) # This should be 'str'
(related #2980)
A similar idea was discussed in #1749, but emitting an error on if 'a' in [1, 2, 3]: ...
would require a larger change: emitting errors on unreachable code in binder.
Metadata
Metadata
Assignees
Labels
No labels
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
elazarg commentedon Oct 8, 2017
I think this can also fall out of #4063 (just as a note; of course a dedicated PR is more practical)
gvanrossum commentedon Oct 8, 2017
ilevkivskyi commentedon Oct 8, 2017
@gvanrossum
OK, makes sense, we should not narrow down if we start from
Any
and should not use promotions (this is actually default inis_overlapping_types
). I will update the PR now.ilevkivskyi commentedon Oct 8, 2017
@gvanrossum OK, I updated PR #4072
Now it does not narrow type from
Any
and does not use promotions:It is however not easy to prohibit this:
This is still formally speaking unsafe, but I think it is a reasonable price to pay.
Narrow types after 'in' operator (#4072)
in
operator does not check type of element #4645