Check for dangerous non-overlapping comparisons like 42 == 'no'. The original_container is the original container type for 'in' checks (and None for equality checks). Rules: * X and None are overlapping even in strict-optional mode. This is to allow
(
self,
left: Type,
right: Type,
*,
original_container: Type | None = None,
seen_types: set[tuple[Type, Type]] | None = None,
prefer_literal: bool = True,
identity_check: bool = False,
)
| 3845 | return None |
| 3846 | |
| 3847 | def dangerous_comparison( |
| 3848 | self, |
| 3849 | left: Type, |
| 3850 | right: Type, |
| 3851 | *, |
| 3852 | original_container: Type | None = None, |
| 3853 | seen_types: set[tuple[Type, Type]] | None = None, |
| 3854 | prefer_literal: bool = True, |
| 3855 | identity_check: bool = False, |
| 3856 | ) -> bool: |
| 3857 | """Check for dangerous non-overlapping comparisons like 42 == 'no'. |
| 3858 | |
| 3859 | The original_container is the original container type for 'in' checks |
| 3860 | (and None for equality checks). |
| 3861 | |
| 3862 | Rules: |
| 3863 | * X and None are overlapping even in strict-optional mode. This is to allow |
| 3864 | 'assert x is not None' for x defined as 'x = None # type: str' in class body |
| 3865 | (otherwise mypy itself would have couple dozen errors because of this). |
| 3866 | * Optional[X] and Optional[Y] are non-overlapping if X and Y are |
| 3867 | non-overlapping, although technically None is overlap, it is most |
| 3868 | likely an error. |
| 3869 | * Any overlaps with everything, i.e. always safe. |
| 3870 | * Special case: b'abc' in b'cde' is safe. |
| 3871 | """ |
| 3872 | if not self.chk.options.strict_equality: |
| 3873 | return False |
| 3874 | |
| 3875 | if seen_types is None: |
| 3876 | seen_types = set() |
| 3877 | if (left, right) in seen_types: |
| 3878 | return False |
| 3879 | seen_types.add((left, right)) |
| 3880 | |
| 3881 | left, right = get_proper_types((left, right)) |
| 3882 | |
| 3883 | # We suppress the error for equality and container checks if there is a custom __eq__() |
| 3884 | # method on either side. User defined (or even standard library) classes can define this |
| 3885 | # to return True for comparisons between non-overlapping types. |
| 3886 | if ( |
| 3887 | custom_special_method(left, "__eq__") or custom_special_method(right, "__eq__") |
| 3888 | ) and not identity_check: |
| 3889 | return False |
| 3890 | |
| 3891 | if prefer_literal: |
| 3892 | # Also flag non-overlapping literals in situations like: |
| 3893 | # x: Literal['a', 'b'] |
| 3894 | # if x == 'c': |
| 3895 | # ... |
| 3896 | left = try_getting_literal(left) |
| 3897 | right = try_getting_literal(right) |
| 3898 | |
| 3899 | if self.chk.binder.is_unreachable_warning_suppressed(): |
| 3900 | # We are inside a function that contains type variables with value restrictions in |
| 3901 | # its signature. In this case we just suppress all strict-equality checks to avoid |
| 3902 | # false positives for code like: |
| 3903 | # |
| 3904 | # T = TypeVar('T', str, int) |
no test coverage detected