From e61657ff3cfd1e476c5a016dfbd25ecb5e65a8e3 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Fri, 9 Jan 2026 11:58:43 +0100 Subject: [PATCH] [ty] Enable `unused-type-ignore-comment` by default (#22474) --- .github/mypy-primer-ty.toml | 1 - crates/ruff_benchmark/benches/ty.rs | 9 ++++++-- crates/ruff_benchmark/benches/ty_walltime.rs | 22 +++++++++++++------ crates/ty/docs/rules.md | 15 ++++++++----- crates/ty_project/src/metadata/options.rs | 2 +- ...__bases__`_lists_wi…_(ea7ebc83ec359b54).snap | 4 ++-- ...Multiple_unused_comm…_(7cbe4a1d9893a05).snap | 8 +++---- ...€¦_-_Nested_comments_(6e4dc67270e388d2).snap | 4 ++-- crates/ty_python_semantic/src/suppression.rs | 12 ++++++---- ty.schema.json | 6 ++--- 10 files changed, 52 insertions(+), 31 deletions(-) diff --git a/.github/mypy-primer-ty.toml b/.github/mypy-primer-ty.toml index a64ea72eba..c0bcd88695 100644 --- a/.github/mypy-primer-ty.toml +++ b/.github/mypy-primer-ty.toml @@ -5,5 +5,4 @@ [rules] possibly-unresolved-reference = "warn" possibly-missing-import = "warn" -unused-ignore-comment = "warn" division-by-zero = "warn" diff --git a/crates/ruff_benchmark/benches/ty.rs b/crates/ruff_benchmark/benches/ty.rs index 0252d5c75b..1270800206 100644 --- a/crates/ruff_benchmark/benches/ty.rs +++ b/crates/ruff_benchmark/benches/ty.rs @@ -15,7 +15,7 @@ use ruff_db::files::{File, system_path_to_file}; use ruff_db::source::source_text; use ruff_db::system::{InMemorySystem, MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem}; use ruff_python_ast::PythonVersion; -use ty_project::metadata::options::{EnvironmentOptions, Options}; +use ty_project::metadata::options::{AnalysisOptions, EnvironmentOptions, Options}; use ty_project::metadata::value::{RangedValue, RelativePathBuf}; use ty_project::watch::{ChangeEvent, ChangedKind}; use ty_project::{CheckMode, Db, ProjectDatabase, ProjectMetadata}; @@ -67,6 +67,7 @@ fn tomllib_path(file: &TestFile) -> SystemPathBuf { SystemPathBuf::from("src").join(file.name()) } +#[expect(clippy::needless_update)] fn setup_tomllib_case() -> Case { let system = TestSystem::default(); let fs = system.memory_file_system().clone(); @@ -85,6 +86,10 @@ fn setup_tomllib_case() -> Case { python_version: Some(RangedValue::cli(PythonVersion::PY312)), ..EnvironmentOptions::default() }), + analysis: Some(AnalysisOptions { + respect_type_ignore_comments: Some(false), + ..AnalysisOptions::default() + }), ..Options::default() }); @@ -755,7 +760,7 @@ fn datetype(criterion: &mut Criterion) { max_dep_date: "2025-07-04", python_version: PythonVersion::PY313, }, - 2, + 4, ); bench_project(&benchmark, criterion); diff --git a/crates/ruff_benchmark/benches/ty_walltime.rs b/crates/ruff_benchmark/benches/ty_walltime.rs index d6391b9465..e1ba047eba 100644 --- a/crates/ruff_benchmark/benches/ty_walltime.rs +++ b/crates/ruff_benchmark/benches/ty_walltime.rs @@ -71,6 +71,8 @@ impl Display for Benchmark<'_> { } } +#[track_caller] +#[expect(clippy::cast_precision_loss)] fn check_project(db: &ProjectDatabase, project_name: &str, max_diagnostics: usize) { let result = db.check(); let diagnostics = result.len(); @@ -79,6 +81,12 @@ fn check_project(db: &ProjectDatabase, project_name: &str, max_diagnostics: usiz diagnostics > 1 && diagnostics <= max_diagnostics, "Expected between 1 and {max_diagnostics} diagnostics on project '{project_name}' but got {diagnostics}", ); + + if (max_diagnostics - diagnostics) as f64 / max_diagnostics as f64 > 0.10 { + tracing::warn!( + "The expected diagnostics for project `{project_name}` can be reduced: expected {max_diagnostics} but got {diagnostics}" + ); + } } static ALTAIR: Benchmark = Benchmark::new( @@ -101,7 +109,7 @@ static ALTAIR: Benchmark = Benchmark::new( max_dep_date: "2025-06-17", python_version: PythonVersion::PY312, }, - 1000, + 850, ); static COLOUR_SCIENCE: Benchmark = Benchmark::new( @@ -120,7 +128,7 @@ static COLOUR_SCIENCE: Benchmark = Benchmark::new( max_dep_date: "2025-06-17", python_version: PythonVersion::PY310, }, - 1070, + 350, ); static FREQTRADE: Benchmark = Benchmark::new( @@ -163,7 +171,7 @@ static PANDAS: Benchmark = Benchmark::new( max_dep_date: "2025-06-17", python_version: PythonVersion::PY312, }, - 4000, + 3800, ); static PYDANTIC: Benchmark = Benchmark::new( @@ -181,7 +189,7 @@ static PYDANTIC: Benchmark = Benchmark::new( max_dep_date: "2025-06-17", python_version: PythonVersion::PY39, }, - 7000, + 3200, ); static SYMPY: Benchmark = Benchmark::new( @@ -194,7 +202,7 @@ static SYMPY: Benchmark = Benchmark::new( max_dep_date: "2025-06-17", python_version: PythonVersion::PY312, }, - 13116, + 13400, ); static TANJUN: Benchmark = Benchmark::new( @@ -207,7 +215,7 @@ static TANJUN: Benchmark = Benchmark::new( max_dep_date: "2025-06-17", python_version: PythonVersion::PY312, }, - 320, + 110, ); static STATIC_FRAME: Benchmark = Benchmark::new( @@ -223,7 +231,7 @@ static STATIC_FRAME: Benchmark = Benchmark::new( max_dep_date: "2025-08-09", python_version: PythonVersion::PY311, }, - 1100, + 1657, ); #[track_caller] diff --git a/crates/ty/docs/rules.md b/crates/ty/docs/rules.md index eb6d62eb85..4a15c1c29b 100644 --- a/crates/ty/docs/rules.md +++ b/crates/ty/docs/rules.md @@ -467,7 +467,7 @@ def test(): -> "int": Default level: warn · Added in 0.0.1-alpha.1 · Related issues · -View source +View source @@ -1047,7 +1047,7 @@ class D(Generic[U, T]): ... Default level: warn · Added in 0.0.1-alpha.1 · Related issues · -View source +View source @@ -2895,7 +2895,7 @@ A() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A' ## `unused-ignore-comment` -Default level: ignore · +Default level: warn · Added in 0.0.1-alpha.1 · Related issues · View source @@ -2904,11 +2904,11 @@ Added in 0. **What it does** -Checks for `type: ignore` or `ty: ignore` directives that are no longer applicable. +Checks for `ty: ignore` or `type: ignore` directives that are no longer applicable. **Why is this bad?** -A `type: ignore` directive that no longer matches any diagnostic violations is likely +A `ty: ignore` directive that no longer matches any diagnostic violations is likely included by mistake, and should be removed to avoid confusion. **Examples** @@ -2923,6 +2923,11 @@ Use instead: a = 20 / 2 ``` +**Options** + +Set [`analysis.respect-type-ignore-comments`](https://docs.astral.sh/ty/reference/configuration/#respect-type-ignore-comments) +to `false` to prevent this rule from reporting unused `type: ignore` comments. + ## `useless-overload-body` diff --git a/crates/ty_project/src/metadata/options.rs b/crates/ty_project/src/metadata/options.rs index a3cc86ef34..a250baa982 100644 --- a/crates/ty_project/src/metadata/options.rs +++ b/crates/ty_project/src/metadata/options.rs @@ -1292,7 +1292,7 @@ pub struct AnalysisOptions { respect-type-ignore-comments = false "# )] - respect_type_ignore_comments: Option, + pub respect_type_ignore_comments: Option, } impl AnalysisOptions { diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/mro.md_-_Method_Resolution_Or…_-_`__bases__`_lists_wi…_(ea7ebc83ec359b54).snap b/crates/ty_python_semantic/resources/mdtest/snapshots/mro.md_-_Method_Resolution_Or…_-_`__bases__`_lists_wi…_(ea7ebc83ec359b54).snap index 18f5ecedf7..eb6d577069 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/mro.md_-_Method_Resolution_Or…_-_`__bases__`_lists_wi…_(ea7ebc83ec359b54).snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/mro.md_-_Method_Resolution_Or…_-_`__bases__`_lists_wi…_(ea7ebc83ec359b54).snap @@ -304,7 +304,7 @@ info: rule `duplicate-base` is enabled by default ``` ``` -info[unused-ignore-comment]: Unused blanket `type: ignore` directive +warning[unused-ignore-comment]: Unused blanket `type: ignore` directive --> src/mdtest_snippet.py:72:9 | 70 | A, @@ -356,7 +356,7 @@ info: rule `duplicate-base` is enabled by default ``` ``` -info[unused-ignore-comment]: Unused blanket `type: ignore` directive +warning[unused-ignore-comment]: Unused blanket `type: ignore` directive --> src/mdtest_snippet.py:81:13 | 79 | ): diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/ty_ignore.md_-_Suppressing_errors_w…_-_Multiple_unused_comm…_(7cbe4a1d9893a05).snap b/crates/ty_python_semantic/resources/mdtest/snapshots/ty_ignore.md_-_Suppressing_errors_w…_-_Multiple_unused_comm…_(7cbe4a1d9893a05).snap index 5299372d53..9bd24985d0 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/ty_ignore.md_-_Suppressing_errors_w…_-_Multiple_unused_comm…_(7cbe4a1d9893a05).snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/ty_ignore.md_-_Suppressing_errors_w…_-_Multiple_unused_comm…_(7cbe4a1d9893a05).snap @@ -27,7 +27,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/suppressions/ty_ignore.m # Diagnostics ``` -info[unused-ignore-comment]: Unused `ty: ignore` directive +warning[unused-ignore-comment]: Unused `ty: ignore` directive --> src/mdtest_snippet.py:2:13 | 1 | # error: [unused-ignore-comment] "Unused `ty: ignore` directive" @@ -47,7 +47,7 @@ help: Remove the unused suppression comment ``` ``` -info[unused-ignore-comment]: Unused `ty: ignore` directive: 'invalid-assignment' +warning[unused-ignore-comment]: Unused `ty: ignore` directive: 'invalid-assignment' --> src/mdtest_snippet.py:6:26 | 4 | # error: [unused-ignore-comment] "Unused `ty: ignore` directive: 'invalid-assignment'" @@ -70,7 +70,7 @@ help: Remove the unused suppression code ``` ``` -info[unused-ignore-comment]: Unused `ty: ignore` directive: 'unresolved-reference' +warning[unused-ignore-comment]: Unused `ty: ignore` directive: 'unresolved-reference' --> src/mdtest_snippet.py:6:64 | 4 | # error: [unused-ignore-comment] "Unused `ty: ignore` directive: 'invalid-assignment'" @@ -93,7 +93,7 @@ help: Remove the unused suppression code ``` ``` -info[unused-ignore-comment]: Unused `ty: ignore` directive: 'invalid-assignment', 'unresolved-reference' +warning[unused-ignore-comment]: Unused `ty: ignore` directive: 'invalid-assignment', 'unresolved-reference' --> src/mdtest_snippet.py:9:26 | 8 | # error: [unused-ignore-comment] "Unused `ty: ignore` directive: 'invalid-assignment', 'unresolved-reference'" diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/type_ignore.md_-_Suppressing_errors_w…_-_Nested_comments_(6e4dc67270e388d2).snap b/crates/ty_python_semantic/resources/mdtest/snapshots/type_ignore.md_-_Suppressing_errors_w…_-_Nested_comments_(6e4dc67270e388d2).snap index ffe10ed75e..5e8ac905fa 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/type_ignore.md_-_Suppressing_errors_w…_-_Nested_comments_(6e4dc67270e388d2).snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/type_ignore.md_-_Suppressing_errors_w…_-_Nested_comments_(6e4dc67270e388d2).snap @@ -32,7 +32,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/suppressions/type_ignore # Diagnostics ``` -info[unused-ignore-comment]: Unused `ty: ignore` directive +warning[unused-ignore-comment]: Unused `ty: ignore` directive --> src/mdtest_snippet.py:10:9 | 8 | a = (3 @@ -55,7 +55,7 @@ help: Remove the unused suppression comment ``` ``` -info[unused-ignore-comment]: Unused `ty: ignore` directive +warning[unused-ignore-comment]: Unused `ty: ignore` directive --> src/mdtest_snippet.py:14:21 | 12 | a = (3 diff --git a/crates/ty_python_semantic/src/suppression.rs b/crates/ty_python_semantic/src/suppression.rs index 7b9794031c..5161c65922 100644 --- a/crates/ty_python_semantic/src/suppression.rs +++ b/crates/ty_python_semantic/src/suppression.rs @@ -24,10 +24,10 @@ use crate::{Db, declare_lint, lint::LintId}; declare_lint! { /// ## What it does - /// Checks for `type: ignore` or `ty: ignore` directives that are no longer applicable. + /// Checks for `ty: ignore` or `type: ignore` directives that are no longer applicable. /// /// ## Why is this bad? - /// A `type: ignore` directive that no longer matches any diagnostic violations is likely + /// A `ty: ignore` directive that no longer matches any diagnostic violations is likely /// included by mistake, and should be removed to avoid confusion. /// /// ## Examples @@ -40,10 +40,14 @@ declare_lint! { /// ```py /// a = 20 / 2 /// ``` + /// + /// ## Options + /// Set [`analysis.respect-type-ignore-comments`](https://docs.astral.sh/ty/reference/configuration/#respect-type-ignore-comments) + /// to `false` to prevent this rule from reporting unused `type: ignore` comments. pub static UNUSED_IGNORE_COMMENT = { - summary: "detects unused `type: ignore` comments", + summary: "detects unused `ty: ignore` and `type: ignore` comments", status: LintStatus::stable("0.0.1-alpha.1"), - default_level: Level::Ignore, + default_level: Level::Warn, } } diff --git a/ty.schema.json b/ty.schema.json index 7e1f86ac65..458cb9c2af 100644 --- a/ty.schema.json +++ b/ty.schema.json @@ -1171,9 +1171,9 @@ ] }, "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```", - "default": "ignore", + "title": "detects unused `ty: ignore` and `type: ignore` comments", + "description": "## What it does\nChecks for `ty: ignore` or `type: ignore` directives that are no longer applicable.\n\n## Why is this bad?\nA `ty: 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```\n\n## Options\nSet [`analysis.respect-type-ignore-comments`](https://docs.astral.sh/ty/reference/configuration/#respect-type-ignore-comments)\nto `false` to prevent this rule from reporting unused `type: ignore` comments.", + "default": "warn", "oneOf": [ { "$ref": "#/definitions/Level"