diff --git a/.github/mypy-primer-ty.toml b/.github/mypy-primer-ty.toml
index 9317364fe2..eea5cb4774 100644
--- a/.github/mypy-primer-ty.toml
+++ b/.github/mypy-primer-ty.toml
@@ -5,4 +5,4 @@
[rules]
possibly-unresolved-reference = "warn"
unused-ignore-comment = "warn"
-division-by-zero = "warn"
+literal-math-error = "warn"
diff --git a/crates/ty/docs/configuration.md b/crates/ty/docs/configuration.md
index f2a39837fa..343d87f099 100644
--- a/crates/ty/docs/configuration.md
+++ b/crates/ty/docs/configuration.md
@@ -23,7 +23,7 @@ Valid severities are:
```toml
[tool.ty.rules]
possibly-unresolved-reference = "warn"
-division-by-zero = "ignore"
+literal-math-error = "ignore"
```
---
diff --git a/crates/ty/docs/rules.md b/crates/ty/docs/rules.md
index 39e60651a9..b0f0817fe5 100644
--- a/crates/ty/docs/rules.md
+++ b/crates/ty/docs/rules.md
@@ -177,7 +177,7 @@ class B(A): ...
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20duplicate-base) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L263)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L266)
**What it does**
@@ -202,7 +202,7 @@ class B(A, A): ...
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20duplicate-kw-only) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L284)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L287)
**What it does**
@@ -306,7 +306,7 @@ def test(): -> "Literal[5]":
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20inconsistent-mro) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L426)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L429)
**What it does**
@@ -334,7 +334,7 @@ class C(A, B): ...
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20index-out-of-bounds) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L450)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L453)
**What it does**
@@ -358,7 +358,7 @@ t[3] # IndexError: tuple index out of range
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20instance-layout-conflict) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L316)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L319)
**What it does**
@@ -445,7 +445,7 @@ an atypical memory layout.
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-argument-type) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L470)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L473)
**What it does**
@@ -470,7 +470,7 @@ func("foo") # error: [invalid-argument-type]
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-assignment) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L510)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L513)
**What it does**
@@ -496,7 +496,7 @@ a: int = ''
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-attribute-access) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1514)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1517)
**What it does**
@@ -528,7 +528,7 @@ C.instance_var = 3 # error: Cannot assign to instance variable
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-base) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L532)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L535)
**What it does**
@@ -550,7 +550,7 @@ class A(42): ... # error: [invalid-base]
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-context-manager) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L583)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L586)
**What it does**
@@ -575,7 +575,7 @@ with 1:
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-declaration) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L604)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L607)
**What it does**
@@ -602,7 +602,7 @@ a: str
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-exception-caught) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L627)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L630)
**What it does**
@@ -644,7 +644,7 @@ except ZeroDivisionError:
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-generic-class) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L663)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L666)
**What it does**
@@ -675,7 +675,7 @@ class C[U](Generic[T]): ...
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-legacy-type-variable) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L689)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L692)
**What it does**
@@ -708,7 +708,7 @@ def f(t: TypeVar("U")): ...
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-metaclass) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L738)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L741)
**What it does**
@@ -740,7 +740,7 @@ class B(metaclass=f): ...
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-overload) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L765)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L768)
**What it does**
@@ -788,7 +788,7 @@ def foo(x: int) -> int: ...
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-parameter-default) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L808)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L811)
**What it does**
@@ -812,7 +812,7 @@ def f(a: int = ''): ...
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-protocol) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L398)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L401)
**What it does**
@@ -844,7 +844,7 @@ TypeError: Protocols can only inherit from other protocols, got
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-raise) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L828)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L831)
Checks for `raise` statements that raise non-exceptions or use invalid
@@ -891,7 +891,7 @@ def g():
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-return-type) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L491)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L494)
**What it does**
@@ -914,7 +914,7 @@ def func() -> int:
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-super-argument) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L871)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L874)
**What it does**
@@ -968,7 +968,7 @@ TODO #14889
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-alias-type) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L717)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L720)
**What it does**
@@ -993,7 +993,7 @@ NewAlias = TypeAliasType(get_name(), int) # error: TypeAliasType name mus
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-checking-constant) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L910)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L913)
**What it does**
@@ -1021,7 +1021,7 @@ TYPE_CHECKING = ''
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-form) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L934)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L937)
**What it does**
@@ -1049,7 +1049,7 @@ b: Annotated[int] # `Annotated` expects at least two arguments
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-guard-call) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L986)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L989)
**What it does**
@@ -1081,7 +1081,7 @@ f(10) # Error
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-guard-definition) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L958)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L961)
**What it does**
@@ -1113,7 +1113,7 @@ class C:
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-variable-constraints) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1014)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1017)
**What it does**
@@ -1146,7 +1146,7 @@ T = TypeVar('T', bound=str) # valid bound TypeVar
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20missing-argument) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1043)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1046)
**What it does**
@@ -1169,7 +1169,7 @@ func() # TypeError: func() missing 1 required positional argument: 'x'
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20no-matching-overload) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1062)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1065)
**What it does**
@@ -1196,7 +1196,7 @@ func("string") # error: [no-matching-overload]
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20non-subscriptable) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1085)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1088)
**What it does**
@@ -1218,7 +1218,7 @@ Subscripting an object that does not support it will raise a `TypeError` at runt
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20not-iterable) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1103)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1106)
**What it does**
@@ -1242,7 +1242,7 @@ for i in 34: # TypeError: 'int' object is not iterable
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20parameter-already-assigned) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1154)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1157)
**What it does**
@@ -1296,7 +1296,7 @@ def test(): -> "int":
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20static-assert-error) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1490)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1493)
**What it does**
@@ -1324,7 +1324,7 @@ static_assert(int(2.0 * 3.0) == 6) # error: does not have a statically known tr
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20subclass-of-final-class) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1245)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1248)
**What it does**
@@ -1351,7 +1351,7 @@ class B(A): ... # Error raised here
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20too-many-positional-arguments) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1290)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1293)
**What it does**
@@ -1376,7 +1376,7 @@ f("foo") # Error raised here
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20type-assertion-failure) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1268)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1271)
**What it does**
@@ -1402,7 +1402,7 @@ def _(x: int):
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unavailable-implicit-super-arguments) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1311)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1314)
**What it does**
@@ -1446,7 +1446,7 @@ class A:
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unknown-argument) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1368)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1371)
**What it does**
@@ -1471,7 +1471,7 @@ f(x=1, y=2) # Error raised here
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-attribute) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1389)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1392)
**What it does**
@@ -1497,7 +1497,7 @@ A().foo # AttributeError: 'A' object has no attribute 'foo'
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-import) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1411)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1414)
**What it does**
@@ -1520,7 +1520,7 @@ import foo # ModuleNotFoundError: No module named 'foo'
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-reference) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1430)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1433)
**What it does**
@@ -1543,7 +1543,7 @@ print(x) # NameError: name 'x' is not defined
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-bool-conversion) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1123)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1126)
**What it does**
@@ -1578,7 +1578,7 @@ b1 < b2 < b1 # exception raised here
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-operator) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1449)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1452)
**What it does**
@@ -1604,7 +1604,7 @@ A() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A'
Default level: [`error`](../rules.md#rule-levels "This lint has a default level of 'error'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20zero-stepsize-in-slice) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1471)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1474)
**What it does**
@@ -1655,7 +1655,7 @@ a = 20 / 0 # type: ignore
Default level: [`warn`](../rules.md#rule-levels "This lint has a default level of 'warn'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-attribute) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1175)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1178)
**What it does**
@@ -1711,7 +1711,7 @@ A()[0] # TypeError: 'A' object is not subscriptable
Default level: [`warn`](../rules.md#rule-levels "This lint has a default level of 'warn'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-import) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1197)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1200)
**What it does**
@@ -1741,7 +1741,7 @@ from module import a # ImportError: cannot import name 'a' from 'module'
Default level: [`warn`](../rules.md#rule-levels "This lint has a default level of 'warn'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20redundant-cast) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1542)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1545)
**What it does**
@@ -1766,7 +1766,7 @@ cast(int, f()) # Redundant
Default level: [`warn`](../rules.md#rule-levels "This lint has a default level of 'warn'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20undefined-reveal) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1350)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1353)
**What it does**
@@ -1809,7 +1809,7 @@ a = 20 / 0 # ty: ignore[division-by-zer]
Use instead:
```py
-a = 20 / 0 # ty: ignore[division-by-zero]
+a = 20 / 0 # ty: ignore[literal-math-error]
```
## `unsupported-base`
@@ -1817,7 +1817,7 @@ a = 20 / 0 # ty: ignore[division-by-zero]
Default level: [`warn`](../rules.md#rule-levels "This lint has a default level of 'warn'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-base) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L550)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L553)
**What it does**
@@ -1849,26 +1849,29 @@ class D(C): ... # error: [unsupported-base]
[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order
-## `division-by-zero`
+## `literal-math-error`
Default level: [`ignore`](../rules.md#rule-levels "This lint has a default level of 'ignore'.") ·
-[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20division-by-zero) ·
+[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20literal-math-error) ·
[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L245)
**What it does**
-It detects division by zero.
+Detects runtime errors that would result from invalid math operations
+between two objects with literal `int` types. Examples include division
+by zero and negative bitshifts.
**Why is this bad?**
-Dividing by zero raises a `ZeroDivisionError` at runtime.
+These math operations will lead to exceptions being raised at runtime.
**Examples**
```python
-5 / 0
+5 / 0 # `ZeroDivisionError`
+1 << -1 # `ValueError: negative shift count`
```
## `possibly-unresolved-reference`
@@ -1876,7 +1879,7 @@ Dividing by zero raises a `ZeroDivisionError` at runtime.
Default level: [`ignore`](../rules.md#rule-levels "This lint has a default level of 'ignore'.") ·
[Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unresolved-reference) ·
-[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1223)
+[View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1226)
**What it does**
@@ -1917,7 +1920,7 @@ included by mistake, and should be removed to avoid confusion.
**Examples**
```py
-a = 20 / 2 # ty: ignore[division-by-zero]
+a = 20 / 2 # ty: ignore[literal-math-error]
```
Use instead:
diff --git a/crates/ty/tests/cli/main.rs b/crates/ty/tests/cli/main.rs
index 14c237a729..8988272c44 100644
--- a/crates/ty/tests/cli/main.rs
+++ b/crates/ty/tests/cli/main.rs
@@ -327,7 +327,7 @@ fn user_configuration() -> anyhow::Result<()> {
"project/ty.toml",
r#"
[rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
"#,
),
(
@@ -356,7 +356,7 @@ fn user_configuration() -> anyhow::Result<()> {
success: false
exit_code: 1
----- stdout -----
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> main.py:2:5
|
2 | y = 4 / 0
@@ -364,7 +364,7 @@ fn user_configuration() -> anyhow::Result<()> {
3 |
4 | for a in range(0, int(y)):
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
error[unresolved-reference]: Name `prin` used when not defined
--> main.py:7:1
@@ -384,13 +384,13 @@ fn user_configuration() -> anyhow::Result<()> {
);
// The user-level configuration sets the severity for `unresolved-reference` to warn.
- // Changing the level for `division-by-zero` has no effect, because the project-level configuration
+ // Changing the level for `literal-math-error` has no effect, because the project-level configuration
// has higher precedence.
case.write_file(
config_directory.join("ty/ty.toml"),
r#"
[rules]
- division-by-zero = "error"
+ literal-math-error = "error"
unresolved-reference = "warn"
"#,
)?;
@@ -401,7 +401,7 @@ fn user_configuration() -> anyhow::Result<()> {
success: true
exit_code: 0
----- stdout -----
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> main.py:2:5
|
2 | y = 4 / 0
@@ -409,7 +409,7 @@ fn user_configuration() -> anyhow::Result<()> {
3 |
4 | for a in range(0, int(y)):
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
warning[unresolved-reference]: Name `prin` used when not defined
--> main.py:7:1
@@ -437,7 +437,7 @@ fn check_specific_paths() -> anyhow::Result<()> {
(
"project/main.py",
r#"
- y = 4 / 0 # error: division-by-zero
+ y = 4 / 0 # error: literal-math-error
"#,
),
(
diff --git a/crates/ty/tests/cli/rule_selection.rs b/crates/ty/tests/cli/rule_selection.rs
index 08560ac6c2..77b8aae54b 100644
--- a/crates/ty/tests/cli/rule_selection.rs
+++ b/crates/ty/tests/cli/rule_selection.rs
@@ -42,7 +42,7 @@ fn configuration_rule_severity() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "warn" # promote to warn
+ literal-math-error = "warn" # promote to warn
unresolved-reference = "ignore"
"#,
)?;
@@ -51,7 +51,7 @@ fn configuration_rule_severity() -> anyhow::Result<()> {
success: true
exit_code: 0
----- stdout -----
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> test.py:2:5
|
2 | y = 4 / 0
@@ -59,7 +59,7 @@ fn configuration_rule_severity() -> anyhow::Result<()> {
3 |
4 | for a in range(0, int(y)):
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
Found 1 diagnostic
@@ -126,7 +126,7 @@ fn cli_rule_severity() -> anyhow::Result<()> {
.arg("--ignore")
.arg("unresolved-reference")
.arg("--warn")
- .arg("division-by-zero")
+ .arg("literal-math-error")
.arg("--warn")
.arg("unresolved-import"),
@r"
@@ -144,7 +144,7 @@ fn cli_rule_severity() -> anyhow::Result<()> {
info: make sure your Python environment is properly configured: https://docs.astral.sh/ty/modules/#python-environment
info: rule `unresolved-import` was selected on the command line
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> test.py:4:5
|
2 | import does_not_exit
@@ -154,7 +154,7 @@ fn cli_rule_severity() -> anyhow::Result<()> {
5 |
6 | for a in range(0, int(y)):
|
- info: rule `division-by-zero` was selected on the command line
+ info: rule `literal-math-error` was selected on the command line
Found 2 diagnostics
@@ -209,14 +209,14 @@ fn cli_rule_severity_precedence() -> anyhow::Result<()> {
.arg("--warn")
.arg("unresolved-reference")
.arg("--warn")
- .arg("division-by-zero")
+ .arg("literal-math-error")
.arg("--ignore")
.arg("unresolved-reference"),
@r"
success: true
exit_code: 0
----- stdout -----
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> test.py:2:5
|
2 | y = 4 / 0
@@ -224,7 +224,7 @@ fn cli_rule_severity_precedence() -> anyhow::Result<()> {
3 |
4 | for a in range(0, int(y)):
|
- info: rule `division-by-zero` was selected on the command line
+ info: rule `literal-math-error` was selected on the command line
Found 1 diagnostic
@@ -299,21 +299,21 @@ fn overrides_basic() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "error"
+ literal-math-error = "error"
unresolved-reference = "error"
[[tool.ty.overrides]]
include = ["tests/**"]
[tool.ty.overrides.rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
unresolved-reference = "ignore"
"#,
),
(
"main.py",
r#"
- y = 4 / 0 # division-by-zero: error (global)
+ y = 4 / 0 # literal-math-error: error (global)
x = 1
prin(x) # unresolved-reference: error (global)
"#,
@@ -321,7 +321,7 @@ fn overrides_basic() -> anyhow::Result<()> {
(
"tests/test_main.py",
r#"
- y = 4 / 0 # division-by-zero: warn (override)
+ y = 4 / 0 # literal-math-error: warn (override)
x = 1
prin(x) # unresolved-reference: ignore (override)
"#,
@@ -332,35 +332,35 @@ fn overrides_basic() -> anyhow::Result<()> {
success: false
exit_code: 1
----- stdout -----
- error[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ error[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> main.py:2:5
|
- 2 | y = 4 / 0 # division-by-zero: error (global)
+ 2 | y = 4 / 0 # literal-math-error: error (global)
| ^^^^^
3 | x = 1
4 | prin(x) # unresolved-reference: error (global)
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
error[unresolved-reference]: Name `prin` used when not defined
--> main.py:4:1
|
- 2 | y = 4 / 0 # division-by-zero: error (global)
+ 2 | y = 4 / 0 # literal-math-error: error (global)
3 | x = 1
4 | prin(x) # unresolved-reference: error (global)
| ^^^^
|
info: rule `unresolved-reference` was selected in the configuration file
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> tests/test_main.py:2:5
|
- 2 | y = 4 / 0 # division-by-zero: warn (override)
+ 2 | y = 4 / 0 # literal-math-error: warn (override)
| ^^^^^
3 | x = 1
4 | prin(x) # unresolved-reference: ignore (override)
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
Found 3 diagnostics
@@ -379,31 +379,31 @@ fn overrides_precedence() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "error"
+ literal-math-error = "error"
# First override: all test files
[[tool.ty.overrides]]
include = ["tests/**"]
[tool.ty.overrides.rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
# Second override: specific test file (takes precedence)
[[tool.ty.overrides]]
include = ["tests/important.py"]
[tool.ty.overrides.rules]
- division-by-zero = "ignore"
+ literal-math-error = "ignore"
"#,
),
(
"tests/test_main.py",
r#"
- y = 4 / 0 # division-by-zero: warn (first override)
+ y = 4 / 0 # literal-math-error: warn (first override)
"#,
),
(
"tests/important.py",
r#"
- y = 4 / 0 # division-by-zero: ignore (second override)
+ y = 4 / 0 # literal-math-error: ignore (second override)
"#,
),
])?;
@@ -412,13 +412,13 @@ fn overrides_precedence() -> anyhow::Result<()> {
success: true
exit_code: 0
----- stdout -----
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> tests/test_main.py:2:5
|
- 2 | y = 4 / 0 # division-by-zero: warn (first override)
+ 2 | y = 4 / 0 # literal-math-error: warn (first override)
| ^^^^^
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
Found 1 diagnostic
@@ -437,25 +437,25 @@ fn overrides_exclude() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "error"
+ literal-math-error = "error"
[[tool.ty.overrides]]
include = ["tests/**"]
exclude = ["tests/important.py"]
[tool.ty.overrides.rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
"#,
),
(
"tests/test_main.py",
r#"
- y = 4 / 0 # division-by-zero: warn (override applies)
+ y = 4 / 0 # literal-math-error: warn (override applies)
"#,
),
(
"tests/important.py",
r#"
- y = 4 / 0 # division-by-zero: error (override excluded)
+ y = 4 / 0 # literal-math-error: error (override excluded)
"#,
),
])?;
@@ -464,21 +464,21 @@ fn overrides_exclude() -> anyhow::Result<()> {
success: false
exit_code: 1
----- stdout -----
- error[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ error[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> tests/important.py:2:5
|
- 2 | y = 4 / 0 # division-by-zero: error (override excluded)
+ 2 | y = 4 / 0 # literal-math-error: error (override excluded)
| ^^^^^
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> tests/test_main.py:2:5
|
- 2 | y = 4 / 0 # division-by-zero: warn (override applies)
+ 2 | y = 4 / 0 # literal-math-error: warn (override applies)
| ^^^^^
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
Found 2 diagnostics
@@ -497,28 +497,28 @@ fn overrides_inherit_global() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
unresolved-reference = "error"
[[tool.ty.overrides]]
include = ["tests/**"]
[tool.ty.overrides.rules]
- # Override only division-by-zero, unresolved-reference should inherit from global
- division-by-zero = "ignore"
+ # Override only literal-math-error, unresolved-reference should inherit from global
+ literal-math-error = "ignore"
"#,
),
(
"main.py",
r#"
- y = 4 / 0 # division-by-zero: warn (global)
+ y = 4 / 0 # literal-math-error: warn (global)
prin(y) # unresolved-reference: error (global)
"#,
),
(
"tests/test_main.py",
r#"
- y = 4 / 0 # division-by-zero: ignore (overridden)
+ y = 4 / 0 # literal-math-error: ignore (overridden)
prin(y) # unresolved-reference: error (inherited from global)
"#,
),
@@ -528,19 +528,19 @@ fn overrides_inherit_global() -> anyhow::Result<()> {
success: false
exit_code: 1
----- stdout -----
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> main.py:2:5
|
- 2 | y = 4 / 0 # division-by-zero: warn (global)
+ 2 | y = 4 / 0 # literal-math-error: warn (global)
| ^^^^^
3 | prin(y) # unresolved-reference: error (global)
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
error[unresolved-reference]: Name `prin` used when not defined
--> main.py:3:1
|
- 2 | y = 4 / 0 # division-by-zero: warn (global)
+ 2 | y = 4 / 0 # literal-math-error: warn (global)
3 | prin(y) # unresolved-reference: error (global)
| ^^^^
|
@@ -549,7 +549,7 @@ fn overrides_inherit_global() -> anyhow::Result<()> {
error[unresolved-reference]: Name `prin` used when not defined
--> tests/test_main.py:3:1
|
- 2 | y = 4 / 0 # division-by-zero: ignore (overridden)
+ 2 | y = 4 / 0 # literal-math-error: ignore (overridden)
3 | prin(y) # unresolved-reference: error (inherited from global)
| ^^^^
|
@@ -572,12 +572,12 @@ fn overrides_invalid_include_glob() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "error"
+ literal-math-error = "error"
[[tool.ty.overrides]]
include = ["tests/[invalid"] # Invalid glob: unclosed bracket
[tool.ty.overrides.rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
"#,
),
(
@@ -603,7 +603,7 @@ fn overrides_invalid_include_glob() -> anyhow::Result<()> {
6 | include = ["tests/[invalid"] # Invalid glob: unclosed bracket
| ^^^^^^^^^^^^^^^^ unclosed character class; missing ']'
7 | [tool.ty.overrides.rules]
- 8 | division-by-zero = "warn"
+ 8 | literal-math-error = "warn"
|
"#);
@@ -618,13 +618,13 @@ fn overrides_invalid_exclude_glob() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "error"
+ literal-math-error = "error"
[[tool.ty.overrides]]
include = ["tests/**"]
exclude = ["***/invalid"] # Invalid glob: triple asterisk
[tool.ty.overrides.rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
"#,
),
(
@@ -651,7 +651,7 @@ fn overrides_invalid_exclude_glob() -> anyhow::Result<()> {
7 | exclude = ["***/invalid"] # Invalid glob: triple asterisk
| ^^^^^^^^^^^^^ Too many stars at position 1
8 | [tool.ty.overrides.rules]
- 9 | division-by-zero = "warn"
+ 9 | literal-math-error = "warn"
|
"#);
@@ -666,12 +666,12 @@ fn overrides_missing_include_exclude() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "error"
+ literal-math-error = "error"
[[tool.ty.overrides]]
# Missing both include and exclude - should warn
[tool.ty.overrides.rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
"#,
),
(
@@ -689,7 +689,7 @@ fn overrides_missing_include_exclude() -> anyhow::Result<()> {
warning[unnecessary-overrides-section]: Unnecessary `overrides` section
--> pyproject.toml:5:1
|
- 3 | division-by-zero = "error"
+ 3 | literal-math-error = "error"
4 |
5 | [[tool.ty.overrides]]
| ^^^^^^^^^^^^^^^^^^^^^ This overrides section applies to all files
@@ -700,13 +700,13 @@ fn overrides_missing_include_exclude() -> anyhow::Result<()> {
info: Restrict the files by adding a pattern to `include` or `exclude`...
info: or remove the `[[overrides]]` section and merge the configuration into the root `[rules]` table if the configuration should apply to all files
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> test.py:2:5
|
2 | y = 4 / 0
| ^^^^^
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
Found 2 diagnostics
@@ -725,12 +725,12 @@ fn overrides_empty_include() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "error"
+ literal-math-error = "error"
[[tool.ty.overrides]]
include = [] # Empty include - won't match any files
[tool.ty.overrides.rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
"#,
),
(
@@ -752,17 +752,17 @@ fn overrides_empty_include() -> anyhow::Result<()> {
6 | include = [] # Empty include - won't match any files
| ^^ This `include` list is empty
7 | [tool.ty.overrides.rules]
- 8 | division-by-zero = "warn"
+ 8 | literal-math-error = "warn"
|
info: Remove the `include` option to match all files or add a pattern to match specific files
- error[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ error[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> test.py:2:5
|
2 | y = 4 / 0
| ^^^^^
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
Found 2 diagnostics
@@ -781,7 +781,7 @@ fn overrides_no_actual_overrides() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "error"
+ literal-math-error = "error"
[[tool.ty.overrides]]
include = ["*.py"] # Has patterns but no rule overrides
@@ -803,7 +803,7 @@ fn overrides_no_actual_overrides() -> anyhow::Result<()> {
warning[useless-overrides-section]: Useless `overrides` section
--> pyproject.toml:5:1
|
- 3 | division-by-zero = "error"
+ 3 | literal-math-error = "error"
4 |
5 | [[tool.ty.overrides]]
| ^^^^^^^^^^^^^^^^^^^^^ This overrides section configures no rules
@@ -814,13 +814,13 @@ fn overrides_no_actual_overrides() -> anyhow::Result<()> {
info: Add a `[overrides.rules]` table...
info: or remove the `[[overrides]]` section if there's nothing to override
- error[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ error[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> test.py:2:5
|
2 | y = 4 / 0
| ^^^^^
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
Found 2 diagnostics
@@ -839,13 +839,13 @@ fn overrides_unknown_rules() -> anyhow::Result<()> {
"pyproject.toml",
r#"
[tool.ty.rules]
- division-by-zero = "error"
+ literal-math-error = "error"
[[tool.ty.overrides]]
include = ["tests/**"]
[tool.ty.overrides.rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
division-by-zer = "error" # incorrect rule name
"#,
),
@@ -871,26 +871,26 @@ fn overrides_unknown_rules() -> anyhow::Result<()> {
--> pyproject.toml:10:1
|
8 | [tool.ty.overrides.rules]
- 9 | division-by-zero = "warn"
+ 9 | literal-math-error = "warn"
10 | division-by-zer = "error" # incorrect rule name
| ^^^^^^^^^^^^^^^
|
- error[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ error[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> main.py:2:5
|
2 | y = 4 / 0
| ^^^^^
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
- warning[division-by-zero]: Cannot divide object of type `Literal[4]` by zero
+ warning[literal-math-error]: Cannot divide object of type `Literal[4]` by zero
--> tests/test_main.py:2:5
|
2 | y = 4 / 0
| ^^^^^
|
- info: rule `division-by-zero` was selected in the configuration file
+ info: rule `literal-math-error` was selected in the configuration file
Found 3 diagnostics
diff --git a/crates/ty/tests/file_watching.rs b/crates/ty/tests/file_watching.rs
index 545c824b1a..427727710d 100644
--- a/crates/ty/tests/file_watching.rs
+++ b/crates/ty/tests/file_watching.rs
@@ -1687,7 +1687,7 @@ fn changes_to_user_configuration() -> anyhow::Result<()> {
config_directory.join("ty/ty.toml").as_std_path(),
r#"
[rules]
- division-by-zero = "ignore"
+ literal-math-error = "ignore"
"#,
)?;
@@ -1710,12 +1710,12 @@ fn changes_to_user_configuration() -> anyhow::Result<()> {
"Expected no diagnostics but got: {diagnostics:#?}"
);
- // Enable division-by-zero in the user configuration with warning severity
+ // Enable literal-math-error in the user configuration with warning severity
update_file(
case.root_path().join("home/.config/ty/ty.toml"),
r#"
[rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
"#,
)?;
@@ -1753,7 +1753,7 @@ fn changes_to_config_file_override() -> anyhow::Result<()> {
context.join_project_path("ty-override.toml").as_std_path(),
r#"
[rules]
- division-by-zero = "ignore"
+ literal-math-error = "ignore"
"#,
)?;
@@ -1770,12 +1770,12 @@ fn changes_to_config_file_override() -> anyhow::Result<()> {
"Expected no diagnostics but got: {diagnostics:#?}"
);
- // Enable division-by-zero in the explicitly specified configuration with warning severity
+ // Enable literal-math-error in the explicitly specified configuration with warning severity
update_file(
case.project_path("ty-override.toml"),
r#"
[rules]
- division-by-zero = "warn"
+ literal-math-error = "warn"
"#,
)?;
diff --git a/crates/ty_project/src/metadata/options.rs b/crates/ty_project/src/metadata/options.rs
index e627e01718..98a62dbca0 100644
--- a/crates/ty_project/src/metadata/options.rs
+++ b/crates/ty_project/src/metadata/options.rs
@@ -67,7 +67,7 @@ pub struct Options {
example = r#"
[tool.ty.rules]
possibly-unresolved-reference = "warn"
- division-by-zero = "ignore"
+ literal-math-error = "ignore"
"#
)]
pub rules: Option,
diff --git a/crates/ty_python_semantic/resources/mdtest/binary/booleans.md b/crates/ty_python_semantic/resources/mdtest/binary/booleans.md
index e0bcca56e9..5017a93178 100644
--- a/crates/ty_python_semantic/resources/mdtest/binary/booleans.md
+++ b/crates/ty_python_semantic/resources/mdtest/binary/booleans.md
@@ -37,8 +37,8 @@ reveal_type(b**b) # revealed: Literal[1]
# Division
reveal_type(a / a) # revealed: float
reveal_type(b / a) # revealed: float
-b / b # error: [division-by-zero] "Cannot divide object of type `Literal[False]` by zero"
-a / b # error: [division-by-zero] "Cannot divide object of type `Literal[True]` by zero"
+b / b # error: [literal-math-error] "Cannot divide object of type `Literal[False]` by zero"
+a / b # error: [literal-math-error] "Cannot divide object of type `Literal[True]` by zero"
# bitwise OR
reveal_type(a | a) # revealed: Literal[True]
diff --git a/crates/ty_python_semantic/resources/mdtest/binary/integers.md b/crates/ty_python_semantic/resources/mdtest/binary/integers.md
index 612f367bcf..c81c8fdb08 100644
--- a/crates/ty_python_semantic/resources/mdtest/binary/integers.md
+++ b/crates/ty_python_semantic/resources/mdtest/binary/integers.md
@@ -135,9 +135,9 @@ reveal_type(int() / 0) # revealed: int | float
# error: "Cannot divide object of type `Literal[1]` by zero"
reveal_type(1 / False) # revealed: float
-# error: [division-by-zero] "Cannot divide object of type `Literal[True]` by zero"
+# error: [literal-math-error] "Cannot divide object of type `Literal[True]` by zero"
True / False
-# error: [division-by-zero] "Cannot divide object of type `Literal[True]` by zero"
+# error: [literal-math-error] "Cannot divide object of type `Literal[True]` by zero"
bool(1) / False
# error: "Cannot divide object of type `float` by zero"
@@ -176,20 +176,21 @@ reveal_type(0 >> 100) # revealed: Literal[0]
reveal_type(-42 >> 100) # revealed: Literal[-1]
```
-It is an error to shift by a negative value. This is handled similarly to `division-by-zero`, above:
+It is an error to shift by a negative value. This is handled similarly to `ZeroDivisionError`
+detection, above:
```py
-# error: [negative-shift] "Cannot left shift object of type `Literal[42]` by a negative value"
+# error: [literal-math-error] "Cannot left shift object of type `Literal[42]` by a negative value"
reveal_type(42 << -3) # revealed: int
-# error: [negative-shift] "Cannot left shift object of type `Literal[0]` by a negative value"
+# error: [literal-math-error]
reveal_type(0 << -3) # revealed: int
-# error: [negative-shift] "Cannot left shift object of type `Literal[-42]` by a negative value"
+# error: [literal-math-error]
reveal_type(-42 << -3) # revealed: int
-# error: [negative-shift] "Cannot right shift object of type `Literal[42]` by a negative value"
+# error: [literal-math-error] "Cannot right shift object of type `Literal[42]` by a negative value"
reveal_type(42 >> -3) # revealed: int
-# error: [negative-shift] "Cannot right shift object of type `Literal[0]` by a negative value"
+# error: [literal-math-error]
reveal_type(0 >> -3) # revealed: int
-# error: [negative-shift] "Cannot right shift object of type `Literal[-42]` by a negative value"
+# error: [literal-math-error]
reveal_type(-42 >> -3) # revealed: int
```
diff --git a/crates/ty_python_semantic/resources/mdtest/binary/unions.md b/crates/ty_python_semantic/resources/mdtest/binary/unions.md
index 1ec0794cc4..58c31dd628 100644
--- a/crates/ty_python_semantic/resources/mdtest/binary/unions.md
+++ b/crates/ty_python_semantic/resources/mdtest/binary/unions.md
@@ -54,6 +54,6 @@ If any of the union elements leads to a division by zero, we will report an erro
```py
def f5(m: int, n: Literal[-1, 0, 1]):
- # error: [division-by-zero] "Cannot divide object of type `int` by zero"
+ # error: [literal-math-error] "Cannot divide object of type `int` by zero"
return m / n
```
diff --git a/crates/ty_python_semantic/resources/mdtest/suppressions/ty_ignore.md b/crates/ty_python_semantic/resources/mdtest/suppressions/ty_ignore.md
index 9a1930f015..3a55491106 100644
--- a/crates/ty_python_semantic/resources/mdtest/suppressions/ty_ignore.md
+++ b/crates/ty_python_semantic/resources/mdtest/suppressions/ty_ignore.md
@@ -34,9 +34,9 @@ a = test + 3 # ty: ignore[possibly-unresolved-reference]
```py
# error: [unused-ignore-comment]
-a = 10 / 2 # ty: ignore[division-by-zero]
-a = 10 / 2 # ty: ignore[division-by-zero, unused-ignore-comment]
-a = 10 / 2 # ty: ignore[unused-ignore-comment, division-by-zero]
+a = 10 / 2 # ty: ignore[literal-math-error]
+a = 10 / 2 # ty: ignore[literal-math-error, unused-ignore-comment]
+a = 10 / 2 # ty: ignore[unused-ignore-comment, literal-math-error]
a = 10 / 2 # ty: ignore[unused-ignore-comment] # type: ignore
a = 10 / 2 # type: ignore # ty: ignore[unused-ignore-comment]
```
@@ -45,7 +45,7 @@ a = 10 / 2 # type: ignore # ty: ignore[unused-ignore-comment]
```py
# error: [unused-ignore-comment] "Unused `ty: ignore` directive: 'unused-ignore-comment'"
-a = 10 / 0 # ty: ignore[division-by-zero, unused-ignore-comment]
+a = 10 / 0 # ty: ignore[literal-math-error, unused-ignore-comment]
```
## Multiple unused comments
@@ -54,13 +54,13 @@ Today, ty emits a diagnostic for every unused code. We might want to group the c
some point in the future.
```py
-# error: [unused-ignore-comment] "Unused `ty: ignore` directive: 'division-by-zero'"
+# error: [unused-ignore-comment] "Unused `ty: ignore` directive: 'literal-math-error'"
# error: [unused-ignore-comment] "Unused `ty: ignore` directive: 'unresolved-reference'"
-a = 10 / 2 # ty: ignore[division-by-zero, unresolved-reference]
+a = 10 / 2 # ty: ignore[literal-math-error, unresolved-reference]
# error: [unused-ignore-comment] "Unused `ty: ignore` directive: 'invalid-assignment'"
# error: [unused-ignore-comment] "Unused `ty: ignore` directive: 'unresolved-reference'"
-a = 10 / 0 # ty: ignore[invalid-assignment, division-by-zero, unresolved-reference]
+a = 10 / 0 # ty: ignore[invalid-assignment, literal-math-error, unresolved-reference]
```
## Multiple suppressions
@@ -96,14 +96,14 @@ reveal_type(a) # ty: ignore[revealed-type]
```py
a = 10 / 0 # ty : ignore
-a = 10 / 0 # ty: ignore [ division-by-zero ]
+a = 10 / 0 # ty: ignore [ literal-math-error ]
```
## Whitespace is optional
```py
# fmt: off
-a = 10 / 0 #ty:ignore[division-by-zero]
+a = 10 / 0 #ty:ignore[literal-math-error]
```
## Trailing codes comma
@@ -111,13 +111,13 @@ a = 10 / 0 #ty:ignore[division-by-zero]
Trailing commas in the codes section are allowed:
```py
-a = 10 / 0 # ty: ignore[division-by-zero,]
+a = 10 / 0 # ty: ignore[literal-math-error,]
```
## Invalid characters in codes
```py
-# error: [division-by-zero]
+# error: [literal-math-error]
# error: [invalid-ignore-comment] "Invalid `ty: ignore` comment: expected a alphanumeric character or `-` or `_` as code"
a = 10 / 0 # ty: ignore[*-*]
```
@@ -127,7 +127,7 @@ a = 10 / 0 # ty: ignore[*-*]
```py
-a = 10 / 0 # ty: ignore[division-by-zero]
+a = 10 / 0 # ty: ignore[literal-math-error]
# ^^^^^^ trailing whitespace
```
@@ -141,7 +141,7 @@ future.
```py
# error: [unresolved-reference]
# error: [invalid-ignore-comment] "Invalid `ty: ignore` comment: expected a comma separating the rule codes"
-a = x / 0 # ty: ignore[division-by-zero unresolved-reference]
+a = x / 0 # ty: ignore[literal-math-error unresolved-reference]
```
## Missing closing bracket
@@ -157,7 +157,7 @@ a = x / 2 # ty: ignore[unresolved-reference
An empty codes array suppresses no-diagnostics and is always useless
```py
-# error: [division-by-zero]
+# error: [literal-math-error]
# error: [unused-ignore-comment] "Unused `ty: ignore` without a code"
a = 4 / 0 # ty: ignore[]
```
@@ -170,9 +170,9 @@ severity: `ty: possibly-undefined-reference=error`
```py
# error: [unused-ignore-comment]
-# ty: ignore[division-by-zero]
+# ty: ignore[literal-math-error]
-a = 4 / 0 # error: [division-by-zero]
+a = 4 / 0 # error: [literal-math-error]
```
## Unknown rule
@@ -185,7 +185,7 @@ a = 10 + 4 # ty: ignore[is-equal-14]
## Code with `lint:` prefix
```py
-# error:[unknown-rule] "Unknown rule `lint:division-by-zero`. Did you mean `division-by-zero`?"
-# error: [division-by-zero]
-a = 10 / 0 # ty: ignore[lint:division-by-zero]
+# error:[unknown-rule] "Unknown rule `lint:literal-math-error`. Did you mean `literal-math-error`?"
+# error: [literal-math-error]
+a = 10 / 0 # ty: ignore[lint:literal-math-error]
```
diff --git a/crates/ty_python_semantic/resources/mdtest/suppressions/type_ignore.md b/crates/ty_python_semantic/resources/mdtest/suppressions/type_ignore.md
index 43e9eedcc2..a261c12d3f 100644
--- a/crates/ty_python_semantic/resources/mdtest/suppressions/type_ignore.md
+++ b/crates/ty_python_semantic/resources/mdtest/suppressions/type_ignore.md
@@ -156,6 +156,6 @@ including module docstrings.
# error: [unused-ignore-comment] "Unused blanket `type: ignore` directive"
# type: ignore
-a = 10 / 0 # error: [division-by-zero]
-b = a / 0 # error: [division-by-zero]
+a = 10 / 0 # error: [literal-math-error]
+b = a / 0 # error: [literal-math-error]
```
diff --git a/crates/ty_python_semantic/resources/mdtest/unreachable.md b/crates/ty_python_semantic/resources/mdtest/unreachable.md
index 2d01b4dbbf..c5742893b5 100644
--- a/crates/ty_python_semantic/resources/mdtest/unreachable.md
+++ b/crates/ty_python_semantic/resources/mdtest/unreachable.md
@@ -520,7 +520,7 @@ if False:
def f():
return
- 1 / 0 # error: [division-by-zero]
+ 1 / 0 # error: [literal-math-error]
```
### Conflicting type information
diff --git a/crates/ty_python_semantic/src/suppression.rs b/crates/ty_python_semantic/src/suppression.rs
index cacdc41ec3..cc45bbf151 100644
--- a/crates/ty_python_semantic/src/suppression.rs
+++ b/crates/ty_python_semantic/src/suppression.rs
@@ -22,7 +22,7 @@ declare_lint! {
///
/// ## Examples
/// ```py
- /// a = 20 / 2 # ty: ignore[division-by-zero]
+ /// a = 20 / 2 # ty: ignore[literal-math-error]
/// ```
///
/// Use instead:
@@ -53,7 +53,7 @@ declare_lint! {
/// Use instead:
///
/// ```py
- /// a = 20 / 0 # ty: ignore[division-by-zero]
+ /// a = 20 / 0 # ty: ignore[literal-math-error]
/// ```
pub(crate) static UNKNOWN_RULE = {
summary: "detects `ty: ignore` comments that reference unknown rules",
@@ -241,7 +241,7 @@ fn check_unused_suppressions(context: &mut CheckSuppressionsContext) {
// This looks silly but it's necessary to check again if a `unused-ignore-comment` is indeed unused
// in case the "unused" directive comes after it:
// ```py
- // a = 10 / 2 # ty: ignore[unused-ignore-comment, division-by-zero]
+ // a = 10 / 2 # ty: ignore[unused-ignore-comment, literal-math-error]
// ```
if context.diagnostics.is_used(suppression.id()) {
continue;
diff --git a/crates/ty_python_semantic/src/types/diagnostic.rs b/crates/ty_python_semantic/src/types/diagnostic.rs
index bf42406a7f..ce1c1c406e 100644
--- a/crates/ty_python_semantic/src/types/diagnostic.rs
+++ b/crates/ty_python_semantic/src/types/diagnostic.rs
@@ -34,7 +34,7 @@ pub(crate) fn register_lints(registry: &mut LintRegistryBuilder) {
registry.register_lint(&CONFLICTING_DECLARATIONS);
registry.register_lint(&CONFLICTING_METACLASS);
registry.register_lint(&CYCLIC_CLASS_DEFINITION);
- registry.register_lint(&DIVISION_BY_ZERO);
+ registry.register_lint(&LITERAL_MATH_ERROR);
registry.register_lint(&DUPLICATE_BASE);
registry.register_lint(&DUPLICATE_KW_ONLY);
registry.register_lint(&INSTANCE_LAYOUT_CONFLICT);
@@ -62,7 +62,6 @@ pub(crate) fn register_lints(registry: &mut LintRegistryBuilder) {
registry.register_lint(&INVALID_TYPE_GUARD_CALL);
registry.register_lint(&INVALID_TYPE_VARIABLE_CONSTRAINTS);
registry.register_lint(&MISSING_ARGUMENT);
- registry.register_lint(&NEGATIVE_SHIFT);
registry.register_lint(&NO_MATCHING_OVERLOAD);
registry.register_lint(&NON_SUBSCRIPTABLE);
registry.register_lint(&NOT_ITERABLE);
@@ -245,17 +244,20 @@ declare_lint! {
declare_lint! {
/// ## What it does
- /// It detects division by zero.
+ /// Detects runtime errors that would result from invalid math operations
+ /// between two objects with literal `int` types. Examples include division
+ /// by zero and negative bitshifts.
///
/// ## Why is this bad?
- /// Dividing by zero raises a `ZeroDivisionError` at runtime.
+ /// These math operations will lead to exceptions being raised at runtime.
///
/// ## Examples
/// ```python
- /// 5 / 0
+ /// 5 / 0 # `ZeroDivisionError`
+ /// 1 << -1 # `ValueError: negative shift count`
/// ```
- pub(crate) static DIVISION_BY_ZERO = {
- summary: "detects division by zero",
+ pub(crate) static LITERAL_MATH_ERROR = {
+ summary: "detects runtime errors such as division by zero or negative bitshifts",
status: LintStatus::preview("1.0.0"),
default_level: Level::Ignore,
}
@@ -1060,25 +1062,6 @@ declare_lint! {
}
}
-declare_lint! {
- /// ## What it does
- /// Detects shifting an int by a negative value.
- ///
- /// ## Why is this bad?
- /// Shifting an int by a negative value raises a `ValueError` at runtime.
- ///
- /// ## Examples
- /// ```python
- /// 42 >> -1
- /// 42 << -1
- /// ```
- pub(crate) static NEGATIVE_SHIFT = {
- summary: "detects shifting an int by a negative value",
- status: LintStatus::preview("1.0.0"),
- default_level: Level::Error,
- }
-}
-
declare_lint! {
/// ## What it does
/// Checks for calls to an overloaded function that do not match any of the overloads.
diff --git a/crates/ty_python_semantic/src/types/infer.rs b/crates/ty_python_semantic/src/types/infer.rs
index 18c895c3a4..e3b384d8f9 100644
--- a/crates/ty_python_semantic/src/types/infer.rs
+++ b/crates/ty_python_semantic/src/types/infer.rs
@@ -89,10 +89,10 @@ use crate::types::call::{Binding, Bindings, CallArgumentTypes, CallArguments, Ca
use crate::types::class::{CodeGeneratorKind, MetaclassErrorKind, SliceLiteral};
use crate::types::diagnostic::{
self, CALL_NON_CALLABLE, CONFLICTING_DECLARATIONS, CONFLICTING_METACLASS,
- CYCLIC_CLASS_DEFINITION, DIVISION_BY_ZERO, DUPLICATE_KW_ONLY, INCONSISTENT_MRO,
- INVALID_ARGUMENT_TYPE, INVALID_ASSIGNMENT, INVALID_ATTRIBUTE_ACCESS, INVALID_BASE,
- INVALID_DECLARATION, INVALID_GENERIC_CLASS, INVALID_PARAMETER_DEFAULT, INVALID_TYPE_FORM,
- INVALID_TYPE_GUARD_CALL, INVALID_TYPE_VARIABLE_CONSTRAINTS, IncompatibleBases, NEGATIVE_SHIFT,
+ CYCLIC_CLASS_DEFINITION, DUPLICATE_KW_ONLY, INCONSISTENT_MRO, INVALID_ARGUMENT_TYPE,
+ INVALID_ASSIGNMENT, INVALID_ATTRIBUTE_ACCESS, INVALID_BASE, INVALID_DECLARATION,
+ INVALID_GENERIC_CLASS, INVALID_PARAMETER_DEFAULT, INVALID_TYPE_FORM, INVALID_TYPE_GUARD_CALL,
+ INVALID_TYPE_VARIABLE_CONSTRAINTS, IncompatibleBases, LITERAL_MATH_ERROR,
POSSIBLY_UNBOUND_IMPLICIT_CALL, POSSIBLY_UNBOUND_IMPORT, TypeCheckDiagnostics,
UNDEFINED_REVEAL, UNRESOLVED_ATTRIBUTE, UNRESOLVED_IMPORT, UNRESOLVED_REFERENCE,
UNSUPPORTED_OPERATOR, report_implicit_return_type, report_instance_layout_conflict,
@@ -1512,7 +1512,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
}
}
- /// Raise a diagnostic if the given type cannot be divided by zero, or is shifted by a negative
+ /// Emit a diagnostic if the given type cannot be divided by zero, or is shifted by a negative
/// value.
///
/// Expects the resolved type of the left side of the binary expression.
@@ -1535,18 +1535,16 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
_ => return false,
};
- let (op, by_what, lint) = match (op, lhs_int) {
- (ast::Operator::Div, _) => ("divide", "by zero", &DIVISION_BY_ZERO),
- (ast::Operator::FloorDiv, _) => ("floor divide", "by zero", &DIVISION_BY_ZERO),
- (ast::Operator::Mod, _) => ("reduce", "modulo zero", &DIVISION_BY_ZERO),
- (ast::Operator::LShift, true) => ("left shift", "by a negative value", &NEGATIVE_SHIFT),
- (ast::Operator::RShift, true) => {
- ("right shift", "by a negative value", &NEGATIVE_SHIFT)
- }
+ let (op, by_what) = match (op, lhs_int) {
+ (ast::Operator::Div, _) => ("divide", "by zero"),
+ (ast::Operator::FloorDiv, _) => ("floor divide", "by zero"),
+ (ast::Operator::Mod, _) => ("reduce", "modulo zero"),
+ (ast::Operator::LShift, true) => ("left shift", "by a negative value"),
+ (ast::Operator::RShift, true) => ("right shift", "by a negative value"),
_ => return false,
};
- if let Some(builder) = self.context.report_lint(lint, node) {
+ if let Some(builder) = self.context.report_lint(&LITERAL_MATH_ERROR, node) {
builder.into_diagnostic(format_args!(
"Cannot {op} object of type `{}` {by_what}",
left.display(self.db())
diff --git a/ty.schema.json b/ty.schema.json
index 55f9827644..d4f7f465ef 100644
--- a/ty.schema.json
+++ b/ty.schema.json
@@ -331,16 +331,6 @@
}
]
},
- "division-by-zero": {
- "title": "detects division by zero",
- "description": "## What it does\nIt detects division by zero.\n\n## Why is this bad?\nDividing by zero raises a `ZeroDivisionError` at runtime.\n\n## Examples\n```python\n5 / 0\n```",
- "default": "ignore",
- "oneOf": [
- {
- "$ref": "#/definitions/Level"
- }
- ]
- },
"duplicate-base": {
"title": "detects class definitions with duplicate bases",
"description": "## What it does\nChecks for class definitions with duplicate bases.\n\n## Why is this bad?\nClass definitions with duplicate bases raise `TypeError` at runtime.\n\n## Examples\n```python\nclass A: ...\n\n# TypeError: duplicate base class\nclass B(A, A): ...\n```",
@@ -661,19 +651,19 @@
}
]
},
- "missing-argument": {
- "title": "detects missing required arguments in a call",
- "description": "## What it does\nChecks for missing required arguments in a call.\n\n## Why is this bad?\nFailing to provide a required argument will raise a `TypeError` at runtime.\n\n## Examples\n```python\ndef func(x: int): ...\nfunc() # TypeError: func() missing 1 required positional argument: 'x'\n```",
- "default": "error",
+ "literal-math-error": {
+ "title": "detects runtime errors such as division by zero or negative bitshifts",
+ "description": "## What it does\nDetects runtime errors that would result from invalid math operations\nbetween two objects with literal `int` types. Examples include division\nby zero and negative bitshifts.\n\n## Why is this bad?\nThese math operations will lead to exceptions being raised at runtime.\n\n## Examples\n```python\n5 / 0 # `ZeroDivisionError`\n1 << -1 # `ValueError: negative shift count`\n```",
+ "default": "ignore",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
- "negative-shift": {
- "title": "detects shifting an int by a negative value",
- "description": "## What it does\nDetects shifting an int by a negative value.\n\n## Why is this bad?\nShifting an int by a negative value raises a `ValueError` at runtime.\n\n## Examples\n```python\n42 >> -1\n42 << -1\n```",
+ "missing-argument": {
+ "title": "detects missing required arguments in a call",
+ "description": "## What it does\nChecks for missing required arguments in a call.\n\n## Why is this bad?\nFailing to provide a required argument will raise a `TypeError` at runtime.\n\n## Examples\n```python\ndef func(x: int): ...\nfunc() # TypeError: func() missing 1 required positional argument: 'x'\n```",
"default": "error",
"oneOf": [
{
@@ -853,7 +843,7 @@
},
"unknown-rule": {
"title": "detects `ty: ignore` comments that reference unknown rules",
- "description": "## What it does\nChecks for `ty: ignore[code]` where `code` isn't a known lint rule.\n\n## Why is this bad?\nA `ty: ignore[code]` directive with a `code` that doesn't match\nany known rule will not suppress any type errors, and is probably a mistake.\n\n## Examples\n```py\na = 20 / 0 # ty: ignore[division-by-zer]\n```\n\nUse instead:\n\n```py\na = 20 / 0 # ty: ignore[division-by-zero]\n```",
+ "description": "## What it does\nChecks for `ty: ignore[code]` where `code` isn't a known lint rule.\n\n## Why is this bad?\nA `ty: ignore[code]` directive with a `code` that doesn't match\nany known rule will not suppress any type errors, and is probably a mistake.\n\n## Examples\n```py\na = 20 / 0 # ty: ignore[division-by-zer]\n```\n\nUse instead:\n\n```py\na = 20 / 0 # ty: ignore[literal-math-error]\n```",
"default": "warn",
"oneOf": [
{
@@ -923,7 +913,7 @@
},
"unused-ignore-comment": {
"title": "detects unused `type: ignore` comments",
- "description": "## What it does\nChecks for `type: ignore` or `ty: ignore` directives that are no longer applicable.\n\n## Why is this bad?\nA `type: ignore` directive that no longer matches any diagnostic violations is likely\nincluded by mistake, and should be removed to avoid confusion.\n\n## Examples\n```py\na = 20 / 2 # ty: ignore[division-by-zero]\n```\n\nUse instead:\n\n```py\na = 20 / 2\n```",
+ "description": "## What it does\nChecks for `type: ignore` or `ty: ignore` directives that are no longer applicable.\n\n## Why is this bad?\nA `type: ignore` directive that no longer matches any diagnostic violations is likely\nincluded by mistake, and should be removed to avoid confusion.\n\n## Examples\n```py\na = 20 / 2 # ty: ignore[literal-math-error]\n```\n\nUse instead:\n\n```py\na = 20 / 2\n```",
"default": "ignore",
"oneOf": [
{