diff --git a/crates/ruff_linter/resources/test/fixtures/ruff/RUF013_0.py b/crates/ruff_linter/resources/test/fixtures/ruff/RUF013_0.py index e4807c9f5ac61..17acae0bb95d1 100644 --- a/crates/ruff_linter/resources/test/fixtures/ruff/RUF013_0.py +++ b/crates/ruff_linter/resources/test/fixtures/ruff/RUF013_0.py @@ -1,5 +1,5 @@ import typing -from typing import Annotated, Any, Literal, Optional, Tuple, Union +from typing import Annotated, Any, Literal, Optional, Tuple, Union, Hashable def f(arg: int): @@ -257,3 +257,13 @@ def f(arg: "Text" = None): def f(arg: MaybeInt = None): pass + + +# Hashable + +def f(arg: Hashable = None): # OK + pass + + +def f(arg: Hashable | int = None): # OK + pass diff --git a/crates/ruff_linter/src/rules/ruff/typing.rs b/crates/ruff_linter/src/rules/ruff/typing.rs index 76f825da8f18a..1c176ca7e4d62 100644 --- a/crates/ruff_linter/src/rules/ruff/typing.rs +++ b/crates/ruff_linter/src/rules/ruff/typing.rs @@ -57,6 +57,9 @@ enum TypingTarget<'a> { /// A `typing.Annotated` type e.g., `Annotated[int, ...]`. Annotated(&'a Expr), + /// The `typing.Hashable` type. + Hashable, + /// Special type used to represent an unknown type (and not a typing target) /// which could be a type alias. Unknown, @@ -121,6 +124,10 @@ impl<'a> TypingTarget<'a> { Some(TypingTarget::Any) } else if matches!(call_path.as_slice(), ["" | "builtins", "object"]) { Some(TypingTarget::Object) + } else if semantic.match_typing_call_path(&call_path, "Hashable") + || matches!(call_path.as_slice(), ["collections", "abc", "Hashable"]) + { + Some(TypingTarget::Hashable) } else if !is_known_type(&call_path, minor_version) { // If it's not a known type, we assume it's `Any`. Some(TypingTarget::Unknown) @@ -142,6 +149,7 @@ impl<'a> TypingTarget<'a> { match self { TypingTarget::None | TypingTarget::Optional(_) + | TypingTarget::Hashable | TypingTarget::Any | TypingTarget::Object | TypingTarget::Unknown => true, @@ -191,6 +199,7 @@ impl<'a> TypingTarget<'a> { // `Literal` cannot contain `Any` as it's a dynamic value. TypingTarget::Literal(_) | TypingTarget::None + | TypingTarget::Hashable | TypingTarget::Object | TypingTarget::Known | TypingTarget::Unknown => false,