diff --git a/crates/ruff_linter/resources/test/fixtures/ruff/RUF009.py b/crates/ruff_linter/resources/test/fixtures/ruff/RUF009.py index 09984cfb2a..a98835577c 100644 --- a/crates/ruff_linter/resources/test/fixtures/ruff/RUF009.py +++ b/crates/ruff_linter/resources/test/fixtures/ruff/RUF009.py @@ -97,3 +97,16 @@ class DataclassWithNewTypeFields: # No errors e: SpecialString = SpecialString("Lorem ipsum") f: NegativeInteger = NegativeInteger(-110) + + +# Test for: +# https://github.com/astral-sh/ruff/issues/15772 +def f() -> int: + return 0 + +@dataclass +class ShouldMatchB008RuleOfImmutableTypeAnnotationIgnored: + this_is_not_fine: list[int] = default_function() + # ignored + this_is_fine: int = f() + diff --git a/crates/ruff_linter/src/rules/ruff/rules/function_call_in_dataclass_default.rs b/crates/ruff_linter/src/rules/ruff/rules/function_call_in_dataclass_default.rs index b5db8114f8..7a514d61fb 100644 --- a/crates/ruff_linter/src/rules/ruff/rules/function_call_in_dataclass_default.rs +++ b/crates/ruff_linter/src/rules/ruff/rules/function_call_in_dataclass_default.rs @@ -3,7 +3,9 @@ use ruff_python_ast::{self as ast, Expr, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, ViolationMetadata}; use ruff_python_ast::name::{QualifiedName, UnqualifiedName}; -use ruff_python_semantic::analyze::typing::{is_immutable_func, is_immutable_newtype_call}; +use ruff_python_semantic::analyze::typing::{ + is_immutable_annotation, is_immutable_func, is_immutable_newtype_call, +}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; @@ -134,6 +136,7 @@ pub(crate) fn function_call_in_dataclass_default(checker: &Checker, class_def: & } if is_field + || is_immutable_annotation(annotation, checker.semantic(), &extend_immutable_calls) || is_class_var_annotation(annotation, checker.semantic()) || is_immutable_func(func, checker.semantic(), &extend_immutable_calls) || is_descriptor_class(func, checker.semantic()) diff --git a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF009_RUF009.py.snap b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF009_RUF009.py.snap index 1ed33b5fa1..8a297d3c15 100644 --- a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF009_RUF009.py.snap +++ b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF009_RUF009.py.snap @@ -1,5 +1,6 @@ --- source: crates/ruff_linter/src/rules/ruff/mod.rs +snapshot_kind: text --- RUF009.py:20:41: RUF009 Do not perform function call `default_function` in dataclass defaults | @@ -89,3 +90,13 @@ RUF009.py:95:19: RUF009 Do not perform function call `Invalid3` in dataclass def 96 | 97 | # No errors | + +RUF009.py:109:35: RUF009 Do not perform function call `default_function` in dataclass defaults + | +107 | @dataclass +108 | class ShouldMatchB008RuleOfImmutableTypeAnnotationIgnored: +109 | this_is_not_fine: list[int] = default_function() + | ^^^^^^^^^^^^^^^^^^ RUF009 +110 | # ignored +111 | this_is_fine: int = f() + | diff --git a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF009_RUF009_attrs_auto_attribs.py.snap b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF009_RUF009_attrs_auto_attribs.py.snap index 0e271a25ce..b3a37c0921 100644 --- a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF009_RUF009_attrs_auto_attribs.py.snap +++ b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF009_RUF009_attrs_auto_attribs.py.snap @@ -1,110 +1,5 @@ --- source: crates/ruff_linter/src/rules/ruff/mod.rs +snapshot_kind: text --- -RUF009_attrs_auto_attribs.py:12:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -10 | a: str = 0 -11 | b = field() -12 | c: int = foo() - | ^^^^^ RUF009 -13 | d = list() - | -RUF009_attrs_auto_attribs.py:20:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -18 | a: str = 0 -19 | b = field() -20 | c: int = foo() - | ^^^^^ RUF009 -21 | d = list() - | - -RUF009_attrs_auto_attribs.py:28:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -26 | a: str = 0 -27 | b = field() -28 | c: int = foo() - | ^^^^^ RUF009 -29 | d = list() - | - -RUF009_attrs_auto_attribs.py:36:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -34 | a: str = 0 -35 | b = field() -36 | c: int = foo() - | ^^^^^ RUF009 -37 | d = list() - | - -RUF009_attrs_auto_attribs.py:44:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -42 | a: str = 0 -43 | b = field() -44 | c: int = foo() - | ^^^^^ RUF009 -45 | d = list() - | - -RUF009_attrs_auto_attribs.py:52:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -50 | a: str = 0 -51 | b = field() -52 | c: int = foo() - | ^^^^^ RUF009 -53 | d = list() - | - -RUF009_attrs_auto_attribs.py:60:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -58 | a: str = 0 -59 | b = field() -60 | c: int = foo() - | ^^^^^ RUF009 -61 | d = list() - | - -RUF009_attrs_auto_attribs.py:68:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -66 | a: str = 0 -67 | b = field() -68 | c: int = foo() - | ^^^^^ RUF009 -69 | d = list() - | - -RUF009_attrs_auto_attribs.py:76:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -74 | a: str = 0 -75 | b = field() -76 | c: int = foo() - | ^^^^^ RUF009 -77 | d = list() - | - -RUF009_attrs_auto_attribs.py:92:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -90 | a: str = 0 -91 | b = field() -92 | c: int = foo() - | ^^^^^ RUF009 -93 | d = list() - | - -RUF009_attrs_auto_attribs.py:100:14: RUF009 Do not perform function call `foo` in dataclass defaults - | - 98 | a: str = 0 - 99 | b = field() -100 | c: int = foo() - | ^^^^^ RUF009 -101 | d = list() - | - -RUF009_attrs_auto_attribs.py:116:14: RUF009 Do not perform function call `foo` in dataclass defaults - | -114 | a: str = 0 -115 | b = field() -116 | c: int = foo() - | ^^^^^ RUF009 -117 | d = list() - |