Files
ruff/crates/red_knot_python_semantic/resources/mdtest/binary/integers.md
David Peter c2f7c39987 [red-knot] mdtest suite: formatting and cleanup (#13806)
Minor cleanup and consistent formatting of the Markdown-based tests.

- Removed lots of unnecessary `a`, `b`, `c`, … variables.
- Moved test assertions (`# revealed:` comments) closer to the tested
object.
- Always separate `# revealed` and `# error` comments from the code by
two spaces, according to the discussion
[here](https://github.com/astral-sh/ruff/pull/13746/files#r1799385758).
This trades readability for consistency in some cases.
- Fixed some headings
2024-10-18 11:07:53 +02:00

1.9 KiB

Binary operations on integers

Basic Arithmetic

reveal_type(2 + 1)  # revealed: Literal[3]
reveal_type(3 - 4)  # revealed: Literal[-1]
reveal_type(3 * -1)  # revealed: Literal[-3]
reveal_type(-3 // 3)  # revealed: Literal[-1]
reveal_type(-3 / 3)  # revealed: float
reveal_type(5 % 3)  # revealed: Literal[2]

Division by Zero

This error is really outside the current Python type system, because e.g. int.__truediv__ and friends are not annotated to indicate that it's an error, and we don't even have a facility to permit such an annotation. So arguably divide-by-zero should be a lint error rather than a type checker error. But we choose to go ahead and error in the cases that are very likely to be an error: dividing something typed as int or float by something known to be Literal[0].

This isn't definitely an error, because the object typed as int or float could be an instance of a custom subclass which overrides division behavior to handle zero without error. But if this unusual case occurs, the error can be avoided by explicitly typing the dividend as that safe custom subclass; we only emit the error if the LHS type is exactly int or float, not if its a subclass.

a = 1 / 0  # error: "Cannot divide object of type `Literal[1]` by zero"
reveal_type(a)  # revealed: float

b = 2 // 0  # error: "Cannot floor divide object of type `Literal[2]` by zero"
reveal_type(b)  # revealed: int

c = 3 % 0  # error: "Cannot reduce object of type `Literal[3]` modulo zero"
reveal_type(c)  # revealed: int

d = int() / 0  # error: "Cannot divide object of type `int` by zero"
# TODO should be int
reveal_type(d)  # revealed: @Todo

e = 1.0 / 0  # error: "Cannot divide object of type `float` by zero"
# TODO should be float
reveal_type(e)  # revealed: @Todo

class MyInt(int): pass

# No error for a subclass of int
# TODO should be float
reveal_type(MyInt(3) / 0)  # revealed: @Todo