diff --git a/crates/ruff_linter/resources/test/fixtures/pyflakes/F811_33.py b/crates/ruff_linter/resources/test/fixtures/pyflakes/F811_33.py new file mode 100644 index 0000000000000..784ed8f074743 --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/pyflakes/F811_33.py @@ -0,0 +1,19 @@ +# Regression test for https://github.com/astral-sh/ruff/issues/19632 +# When @overload is imported from a custom module listed in typing-modules, +# Ruff should recognize it as typing.overload and not emit false F811 +# diagnostics for each overloaded function definition. +# +# Requires: typing-modules = ["std"] +from std import overload + + +@overload +def func(a: str, b: int) -> int: ... + + +@overload +def func(a: int, b: str) -> int: ... + + +def func(a: int | str, b: int | str) -> int: + return 0 diff --git a/crates/ruff_linter/src/rules/pyflakes/mod.rs b/crates/ruff_linter/src/rules/pyflakes/mod.rs index a9d5dd6d02f5d..da594769bc5f3 100644 --- a/crates/ruff_linter/src/rules/pyflakes/mod.rs +++ b/crates/ruff_linter/src/rules/pyflakes/mod.rs @@ -708,6 +708,19 @@ mod tests { Ok(()) } + #[test] + fn f811_typing_modules_overload() -> Result<()> { + let diagnostics = test_path( + Path::new("pyflakes/F811_33.py"), + &LinterSettings { + typing_modules: vec!["std".to_string()], + ..LinterSettings::for_rule(Rule::RedefinedWhileUnused) + }, + )?; + assert_diagnostics!(diagnostics); + Ok(()) + } + #[test] fn extend_generics() -> Result<()> { let snapshot = "extend_immutable_calls".to_string(); diff --git a/crates/ruff_linter/src/rules/pyflakes/snapshots/ruff_linter__rules__pyflakes__tests__f811_typing_modules_overload.snap b/crates/ruff_linter/src/rules/pyflakes/snapshots/ruff_linter__rules__pyflakes__tests__f811_typing_modules_overload.snap new file mode 100644 index 0000000000000..d0b409f39ee0b --- /dev/null +++ b/crates/ruff_linter/src/rules/pyflakes/snapshots/ruff_linter__rules__pyflakes__tests__f811_typing_modules_overload.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff_linter/src/rules/pyflakes/mod.rs +--- + diff --git a/crates/ruff_python_semantic/src/model.rs b/crates/ruff_python_semantic/src/model.rs index 78536071d718c..3cec6a6acb919 100644 --- a/crates/ruff_python_semantic/src/model.rs +++ b/crates/ruff_python_semantic/src/model.rs @@ -209,7 +209,7 @@ impl<'a> SemanticModel<'a> { } if self.typing_modules.iter().any(|module| { - let module = QualifiedName::from_dotted_name(module); + let module = QualifiedName::user_defined(module); qualified_name == &module.append_member(target) }) { return true;