Commit Graph

6616 Commits

Author SHA1 Message Date
Victor Hugo Gomes 67ef370733
[`flake8-use-pathlib`] Fix `PTH116` false positive when `stat` is passed a file descriptor (#17709)
Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-05-01 08:16:28 +02:00
github-actions[bot] e17e1e860b
Sync vendored typeshed stubs (#17753)
Co-authored-by: typeshedbot <>
2025-05-01 07:57:03 +02:00
David Peter 03d8679adf
[red-knot] Preliminary `NamedTuple` support (#17738)
## Summary

Adds preliminary support for `NamedTuple`s, including:
* No false positives when constructing a `NamedTuple` object
* Correct signature for the synthesized `__new__` method, i.e. proper
checking of constructor calls
* A patched MRO (`NamedTuple` => `tuple`), mainly to make type inference
of named attributes possible, but also to better reflect the runtime
MRO.

All of this works:
```py
from typing import NamedTuple

class Person(NamedTuple):
    id: int
    name: str
    age: int | None = None

alice = Person(1, "Alice", 42)
alice = Person(id=1, name="Alice", age=42)

reveal_type(alice.id)  # revealed: int
reveal_type(alice.name)  # revealed: str
reveal_type(alice.age)  # revealed: int | None

# error: [missing-argument]
Person(3)

# error: [too-many-positional-arguments]
Person(3, "Eve", 99, "extra")

# error: [invalid-argument-type]
Person(id="3", name="Eve")
```

Not included:
* type inference for index-based access.
* support for the functional `MyTuple = NamedTuple("MyTuple", […])`
syntax

## Test Plan

New Markdown tests

## Ecosystem analysis

```
                          Diagnostic Analysis Report                           
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━┓
┃ Diagnostic ID                     ┃ Severity ┃ Removed ┃ Added ┃ Net Change ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━┩
│ lint:call-non-callable            │ error    │       0 │     3 │         +3 │
│ lint:call-possibly-unbound-method │ warning  │       0 │     4 │         +4 │
│ lint:invalid-argument-type        │ error    │       0 │    72 │        +72 │
│ lint:invalid-context-manager      │ error    │       0 │     2 │         +2 │
│ lint:invalid-return-type          │ error    │       0 │     2 │         +2 │
│ lint:missing-argument             │ error    │       0 │    46 │        +46 │
│ lint:no-matching-overload         │ error    │   19121 │     0 │     -19121 │
│ lint:not-iterable                 │ error    │       0 │     6 │         +6 │
│ lint:possibly-unbound-attribute   │ warning  │      13 │    32 │        +19 │
│ lint:redundant-cast               │ warning  │       0 │     1 │         +1 │
│ lint:unresolved-attribute         │ error    │       0 │    10 │        +10 │
│ lint:unsupported-operator         │ error    │       3 │     9 │         +6 │
│ lint:unused-ignore-comment        │ warning  │      15 │     4 │        -11 │
├───────────────────────────────────┼──────────┼─────────┼───────┼────────────┤
│ TOTAL                             │          │   19152 │   191 │     -18961 │
└───────────────────────────────────┴──────────┴─────────┴───────┴────────────┘

Analysis complete. Found 13 unique diagnostic IDs.
Total diagnostics removed: 19152
Total diagnostics added: 191
Net change: -18961
```

I uploaded the ecosystem full diff (ignoring the 19k
`no-matching-overload` diagnostics)
[here](https://shark.fish/diff-namedtuple.html).

* There are some new `missing-argument` false positives which come from
the fact that named tuples are often created using unpacking as in
`MyNamedTuple(*fields)`, which we do not understand yet.
* There are some new `unresolved-attribute` false positives, because
methods like `_replace` are not available.
* Lots of the `invalid-argument-type` diagnostics look like true
positives

---------

Co-authored-by: Douglas Creager <dcreager@dcreager.net>
2025-04-30 22:52:04 +02:00
Victor Hugo Gomes d33a503686
[red-knot] Add tests for classes that have incompatible `__new__` and `__init__` methods (#17747)
Closes #17737
2025-04-30 20:40:16 +00:00
Dhruv Manilawala d2a238dfad
[red-knot] Update call binding to return all matching overloads (#17618)
## Summary

This PR updates the existing overload matching methods to return an
iterator of all the matched overloads instead.

This would be useful once the overload call evaluation algorithm is
implemented which should provide an accurate picture of all the matched
overloads. The return type would then be picked from either the only
matched overload or the first overload from the ones that are matched.

In an earlier version of this PR, it tried to check if using an
intersection of return types from the matched overload would help reduce
the false positives but that's not enough. [This
comment](https://github.com/astral-sh/ruff/pull/17618#issuecomment-2842891696)
keep the ecosystem analysis for that change for prosperity.

> [!NOTE]
>
> The best way to review this PR is by hiding the whitespace changes
because there are two instances where a large match expression is
indented to be inside a loop over matching overlods
>
> <img width="1207" alt="Screenshot 2025-04-28 at 15 12 16"
src="https://github.com/user-attachments/assets/e06cbfa4-04fa-435f-84ef-4e5c3c5626d1"
/>

## Test Plan

Make sure existing test cases are unaffected and no ecosystem changes.
2025-05-01 01:33:21 +05:30
Wei Lee 6e765b4527
[`airflow`] apply Replacement::AutoImport to `AIR312` (#17570)
## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

This is not yet fixing anything as the names are not changed, but it
lays down the foundation for fixing.

## Test Plan

<!-- How was it tested? -->

the existing test fixture should already cover this change
2025-04-30 15:53:10 -04:00
Vasco Schiavo c5e41c278c
[`ruff`] Add fix safety section (`RUF028`) (#17722)
The PR add the fix safety section for rule `RUF028`
(https://github.com/astral-sh/ruff/issues/15584 )

See also
[here](https://github.com/astral-sh/ruff/issues/15584#issuecomment-2820424485)
for the reason behind the _unsafe_ of the fix.
2025-04-30 15:06:25 -04:00
Abhijeet Prasad Bodas 0eeb02c0c1
[syntax-errors] Detect single starred expression assignment `x = *y` (#17624)
## Summary

Part of #17412

Starred expressions cannot be used as values in assignment expressions.
Add a new semantic syntax error to catch such instances.
Note that we already have
`ParseErrorType::InvalidStarredExpressionUsage` to catch some starred
expression errors during parsing, but that does not cover top level
assignment expressions.

## Test Plan

- Added new inline tests for the new rule
- Found some examples marked as "valid" in existing tests (`_ = *data`),
which are not really valid (per this new rule) and updated them
- There was an existing inline test - `assign_stmt_invalid_value_expr`
which had instances of `*` expression which would be deemed invalid by
this new rule. Converted these to tuples, so that they do not trigger
this new rule.
2025-04-30 15:04:00 -04:00
Brendan Cooley 5679bf00bc
Fix example syntax for pydocstyle ignore_var_parameters option (#17740)
Co-authored-by: Brendan Cooley <brendanc@ladodgers.com>
2025-04-30 18:19:41 +02:00
Alex Waygood b6de01b9a5
[red-knot] Ban direct instantiation of generic protocols as well as non-generic ones (#17741) 2025-04-30 16:01:28 +00:00
David Peter 18bac94226
[red-knot] Lookup of `__new__` (#17733)
## Summary

Model the lookup of `__new__` without going through
`Type::try_call_dunder`. The `__new__` method is only looked up on the
constructed type itself, not on the meta-type.

This now removes ~930 false positives across the ecosystem (vs 255 for
https://github.com/astral-sh/ruff/pull/17662). It introduces 30 new
false positives related to the construction of enums via something like
`Color = enum.Enum("Color", ["RED", "GREEN"])`. This is expected,
because we don't handle custom metaclass `__call__` methods. The fact
that we previously didn't emit diagnostics there was a coincidence (we
incorrectly called `EnumMeta.__new__`, and since we don't fully
understand its signature, that happened to work with `str`, `list`
arguments).

closes #17462

## Test Plan

Regression test
2025-04-30 17:27:09 +02:00
Dhruv Manilawala 7568eeb7a5
[red-knot] Check decorator consistency on overloads (#17684)
## Summary

Part of #15383.

As per the spec
(https://typing.python.org/en/latest/spec/overload.html#invalid-overload-definitions):

For `@staticmethod` and `@classmethod`:

> If one overload signature is decorated with `@staticmethod` or
`@classmethod`, all overload signatures must be similarly decorated. The
implementation, if present, must also have a consistent decorator. Type
checkers should report an error if these conditions are not met.

For `@final` and `@override`:

> If a `@final` or `@override` decorator is supplied for a function with
overloads, the decorator should be applied only to the overload
implementation if it is present. If an overload implementation isn’t
present (for example, in a stub file), the `@final` or `@override`
decorator should be applied only to the first overload. Type checkers
should enforce these rules and generate an error when they are violated.
If a `@final` or `@override` decorator follows these rules, a type
checker should treat the decorator as if it is present on all overloads.

## Test Plan

Update existing tests; add snapshots.
2025-04-30 20:34:21 +05:30
Hans 0e85cbdd91
[`flake8-use-pathlib`] Avoid suggesting `Path.iterdir()` for `os.listdir` with file descriptor (`PTH208`) (#17715)
## Summary

Fixes: #17695

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-04-30 20:08:57 +05:30
Dhruv Manilawala 7825975972
[red-knot] Check overloads without an implementation (#17681)
## Summary

As mentioned in the spec
(https://typing.python.org/en/latest/spec/overload.html#invalid-overload-definitions),
part of #15383:

> The `@overload`-decorated definitions must be followed by an overload
implementation, which does not include an `@overload` decorator. Type
checkers should report an error or warning if an implementation is
missing. Overload definitions within stub files, protocols, and on
abstract methods within abstract base classes are exempt from this
check.

## Test Plan

Remove TODOs from the test; create one diagnostic snapshot.
2025-04-30 19:54:21 +05:30
Max Mynter f584b66824
Expand Semantic Syntax Coverage (#17725)
Re: #17526 

## Summary
Adds tests to red knot and `linter.rs` for the semantic syntax. 

Specifically add tests for `ReboundComprehensionVariable`,
`DuplicateTypeParameter`, and `MultipleCaseAssignment`.

Refactor the `test_async_comprehension_in_sync_comprehension` →
`test_semantic_error` to be more general for all semantic syntax test
cases.

## Test Plan
This is a test.

## Question
I'm happy to contribute more tests the coming days. 

Should that happen here or should we merge this PR such that the
refactor `test_async_comprehension_in_sync_comprehension` →
`test_semantic_error` is available on main and others can chime in, too?
2025-04-30 10:14:08 -04:00
Dhruv Manilawala ad1a8da4d1
[red-knot] Check for invalid overload usages (#17609)
## Summary

Part of #15383, this PR adds the core infrastructure to check for
invalid overloads and adds a diagnostic to raise if there are < 2
overloads for a given definition.

### Design notes

The requirements to check the overloads are:
* Requires `FunctionType` which has the `to_overloaded` method
* The `FunctionType` **should** be for the function that is either the
implementation or the last overload if the implementation doesn't exists
* Avoid checking any `FunctionType` that are part of an overload chain
* Consider visibility constraints

This required a couple of iteration to make sure all of the above
requirements are fulfilled.

#### 1. Use a set to deduplicate

The logic would first collect all the `FunctionType` that are part of
the overload chain except for the implementation or the last overload if
the implementation doesn't exists. Then, when iterating over all the
function declarations within the scope, we'd avoid checking these
functions. But, this approach would fail to consider visibility
constraints as certain overloads _can_ be behind a version check. Those
aren't part of the overload chain but those aren't a separate overload
chain either.

<details><summary>Implementation:</summary>
<p>

```rs
fn check_overloaded_functions(&mut self) {
    let function_definitions = || {
        self.types
            .declarations
            .iter()
            .filter_map(|(definition, ty)| {
                // Filter out function literals that result from anything other than a function
                // definition e.g., imports.
                if let DefinitionKind::Function(function) = definition.kind(self.db()) {
                    ty.inner_type()
                        .into_function_literal()
                        .map(|ty| (ty, definition.symbol(self.db()), function.node()))
                } else {
                    None
                }
            })
    };

    // A set of all the functions that are part of an overloaded function definition except for
    // the implementation function and the last overload in case the implementation doesn't
    // exists. This allows us to collect all the function definitions that needs to be skipped
    // when checking for invalid overload usages.
    let mut overloads: HashSet<FunctionType<'db>> = HashSet::default();

    for (function, _) in function_definitions() {
        let Some(overloaded) = function.to_overloaded(self.db()) else {
            continue;
        };
        if overloaded.implementation.is_some() {
            overloads.extend(overloaded.overloads.iter().copied());
        } else if let Some((_, previous_overloads)) = overloaded.overloads.split_last() {
            overloads.extend(previous_overloads.iter().copied());
        }
    }

    for (function, function_node) in function_definitions() {
        let Some(overloaded) = function.to_overloaded(self.db()) else {
            continue;
        };
        if overloads.contains(&function) {
            continue;
        }

        // At this point, the `function` variable is either the implementation function or the
        // last overloaded function if the implementation doesn't exists.

        if overloaded.overloads.len() < 2 {
            if let Some(builder) = self
                .context
                .report_lint(&INVALID_OVERLOAD, &function_node.name)
            {
                let mut diagnostic = builder.into_diagnostic(format_args!(
                    "Function `{}` requires at least two overloads",
                    &function_node.name
                ));
                if let Some(first_overload) = overloaded.overloads.first() {
                    diagnostic.annotate(
                        self.context
                            .secondary(first_overload.focus_range(self.db()))
                            .message(format_args!("Only one overload defined here")),
                    );
                }
            }
        }
    }
 }
```

</p>
</details> 

#### 2. Define a `predecessor` query

The `predecessor` query would return the previous `FunctionType` for the
given `FunctionType` i.e., the current logic would be extracted to be a
query instead. This could then be used to make sure that we're checking
the entire overload chain once. The way this would've been implemented
is to have a `to_overloaded` implementation which would take the root of
the overload chain instead of the leaf. But, this would require updates
to the use-def map to somehow be able to return the _following_
functions for a given definition.

#### 3. Create a successor link

This is what Pyrefly uses, we'd create a forward link between two
functions that are involved in an overload chain. This means that for a
given function, we can get the successor function. This could be used to
find the _leaf_ of the overload chain which can then be used with the
`to_overloaded` method to get the entire overload chain. But, this would
also require updating the use-def map to be able to "see" the
_following_ function.

### Implementation 

This leads us to the final implementation that this PR implements which
is to consider the overloaded functions using:
* Collect all the **function symbols** that are defined **and** called
within the same file. This could potentially be an overloaded function
* Use the public bindings to get the leaf of the overload chain and use
that to get the entire overload chain via `to_overloaded` and perform
the check

This has a limitation that in case a function redefines an overload,
then that overload will not be checked. For example:

```py
from typing import overload

@overload
def f() -> None: ...
@overload
def f(x: int) -> int: ...

# The above overload will not be checked as the below function with the same name
# shadows it

def f(*args: int) -> int: ...
```

## Test Plan

Update existing mdtest and add snapshot diagnostics.
2025-04-30 19:37:42 +05:30
Micha Reiser 0861ecfa55
[red-knot] Use 'full' salsa backtrace output that includes durability and revisions (#17735) 2025-04-30 11:04:06 +00:00
Alex Waygood d1f359afbb
[red-knot] Initial support for protocol types (#17682) 2025-04-30 11:03:10 +00:00
Alex Waygood b84b58760e
[red-knot] Computing a type ordering for two non-normalized types is meaningless (#17734) 2025-04-30 11:58:55 +01:00
Micha Reiser d94be0e780
[red-knot] Include salsa backtrace in check and mdtest panic messages (#17732)
Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2025-04-30 10:26:40 +02:00
Alex Waygood 8a6787b39e
[red-knot] Fix control flow for `assert` statements (#17702)
## Summary

@sharkdp and I realised in our 1:1 this morning that our control flow
for `assert` statements isn't quite accurate at the moment. Namely, for
something like this:

```py
def _(x: int | None):
    assert x is None, reveal_type(x)
```

we currently reveal `None` for `x` here, but this is incorrect. In
actual fact, the `msg` expression of an `assert` statement (the
expression after the comma) will only be evaluated if the test (`x is
None`) evaluates to `False`. As such, we should be adding a constraint
of `~None` to `x` in the `msg` expression, which should simplify the
inferred type of `x` to `int` in that context (`(int | None) & ~None` ->
`int`).

## Test Plan

Mdtests added.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-04-30 09:57:49 +02:00
David Peter 4a621c2c12
[red-knot] Fix recording of negative visibility constraints (#17731)
## Summary

We were previously recording wrong reachability constraints for negative
branches. Instead of `[cond] AND (NOT [True])` below, we were recording
`[cond] AND (NOT ([cond] AND [True]))`, i.e. we were negating not just
the last predicate, but the `AND`-ed reachability constraint from last
clause. With this fix, we now record the correct constraints for the
example from #17723:

```py
def _(cond: bool):
    if cond:
        # reachability: [cond]
        if True:
            # reachability: [cond] AND [True]
            pass
        else:
            # reachability: [cond] AND (NOT [True])
            x
```

closes #17723 

## Test Plan

* Regression test.
* Verified the ecosystem changes
2025-04-30 09:32:13 +02:00
Dhruv Manilawala f11d9cb509
[red-knot] Support overloads for callable equivalence (#17698)
## Summary

Part of #15383, this PR adds `is_equivalent_to` support for overloaded
callables.

This is mainly done by delegating it to the subtyping check in that two
types A and B are considered equivalent if A is a subtype of B and B is
a subtype of A.

## Test Plan

Add test cases for overloaded callables in `is_equivalent_to.md`
2025-04-30 02:53:59 +05:30
Victor Hugo Gomes 8c68d30c3a
[`flake8-use-pathlib`] Fix `PTH123` false positive when `open` is passed a file descriptor from a function call (#17705)
## Summary
Includes minor changes to the semantic type inference to help detect the
return type of function call.

Fixes #17691

## Test Plan

Snapshot tests
2025-04-29 16:51:38 -04:00
Alex Waygood 93d6a3567b
[red-knot] mdtest.py: Watch for changes in `red_knot_vendored` and `red_knot_test` as well as in `red_knot_python_semantic` (#17718) 2025-04-29 18:27:49 +00:00
Micha Reiser 1d788981cd
[red-knot] Capture backtrace in "check-failed" diagnostic (#17641)
Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2025-04-29 16:58:58 +00:00
Hans 7d46579808
[docs] fix duplicated 'are' in comment for PTH123 rule (#17714) 2025-04-29 17:58:39 +02:00
Alex Waygood c9a6b1a9d0
[red-knot] Make `Type::signatures()` exhaustive (#17706) 2025-04-29 15:14:08 +01:00
Hans 9b9d16c3ba
[red-knot] colorize concise output diagnostics (#17232) (#17479)
Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Andrew Gallant <andrew@astral.sh>
2025-04-29 16:07:16 +02:00
David Peter 79f8473e51
[red-knot] Assignability of class literals to Callables (#17704)
## Summary

Subtyping was already modeled, but assignability also needs an explicit
branch. Removes 921 ecosystem false positives.

## Test Plan

New Markdown tests.
2025-04-29 15:04:22 +02:00
Douglas Creager ca4fdf452d
Create `TypeVarInstance` type for legacy typevars (#16538)
We are currently representing type variables using a `KnownInstance`
variant, which wraps a `TypeVarInstance` that contains the information
about the typevar (name, bounds, constraints, default type). We were
previously only constructing that type for PEP 695 typevars. This PR
constructs that type for legacy typevars as well.

It also detects functions that are generic because they use legacy
typevars in their parameter list. With the existing logic for inferring
specializations of function calls (#17301), that means that we are
correctly detecting that the definition of `reveal_type` in the typeshed
is generic, and inferring the correct specialization of `_T` for each
call site.

This does not yet handle legacy generic classes; that will come in a
follow-on PR.
2025-04-29 09:03:06 -04:00
Dylan 3c460a7b9a
Make syntax error for unparenthesized except tuples version specific to before 3.14 (#17660)
What it says on the tin 😄
2025-04-29 07:55:30 -05:00
Alex Waygood 31e6576971
[red-knot] micro-optimise `ClassLiteral::is_protocol` (#17703) 2025-04-29 12:35:53 +00:00
Micha Reiser c953e7d143
[red-knot] Improve log message for default python platform (#17700) 2025-04-29 08:26:41 +00:00
Vasco Schiavo 5096824793
[`ruff`] add fix safety section (`RUF017`) (#17480)
The PR add the `fix safety` section for rule `RUF017` (#15584 )
2025-04-28 22:07:22 +00:00
Dylan ae7691b026
Add Python 3.14 to configuration options (#17647)
A small PR that just updates the various settings/configurations to
allow Python 3.14. At the moment selecting that target version will
have no impact compared to Python 3.13 - except that a warning
is emitted if the user does so with `preview` disabled.
2025-04-28 16:29:00 -05:00
Wei Lee 504fa20057
[`airflow`] Apply auto fixes to cases where the names have changed in Airflow 3 (`AIR302`) (#17553)
## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Apply auto fixes to cases where the names have changed in Airflow 3 in
AIR302 and split the huge test cases into different test cases based on
proivder

## Test Plan

<!-- How was it tested? -->

the test cases has been split into multiple for easier checking
2025-04-28 16:35:17 -04:00
Brent Westbrook 01a31c08f5
Add config option to disable `typing_extensions` imports (#17611)
Summary
--

This PR resolves https://github.com/astral-sh/ruff/issues/9761 by adding
a linter configuration option to disable
`typing_extensions` imports. As mentioned [here], it would be ideal if
we could
detect whether or not `typing_extensions` is available as a dependency
automatically, but this seems like a much easier fix in the meantime.

The default for the new option, `typing-extensions`, is `true`,
preserving the current behavior. Setting it to `false` will bail out of
the new
`Checker::typing_importer` method, which has been refactored from the 
`Checker::import_from_typing` method in
https://github.com/astral-sh/ruff/pull/17340),
with `None`, which is then handled specially by each rule that calls it.

I considered some alternatives to a config option, such as checking if
`typing_extensions` has been imported or checking for a `TYPE_CHECKING`
block we could use, but I think defaulting to allowing
`typing_extensions` imports and allowing the user to disable this with
an option is both simple to implement and pretty intuitive.

[here]:
https://github.com/astral-sh/ruff/issues/9761#issuecomment-2790492853

Test Plan
--

New linter tests exercising several combinations of Python versions and
the new config option for PYI019. I also added tests for the other
affected rules, but only in the case where the new config option is
enabled. The rules' existing tests also cover the default case.
2025-04-28 14:57:36 -04:00
Andrew Gallant 405878a128 ruff_db: render file paths in diagnostics as relative paths if possible
This is done in what appears to be the same way as Ruff: we get the CWD,
strip the prefix from the path if possible, and use that. If stripping
the prefix fails, then we print the full path as-is.

Fixes #17233
2025-04-28 14:32:34 -04:00
Andrew Gallant 9a8f3cf247 red_knot_python_semantic: improve `not-iterable` diagnostic
This cleans up one particular TODO by splitting the "because" part of
the `not-iterable` diagnostic out into an info sub-diagnostic.
2025-04-28 11:03:41 -04:00
David Peter 07718f4788
[red-knot] Allow all callables to be assignable to @Todo-signatures (#17680)
## Summary

Removes ~850 diagnostics related to assignability of callable types,
where the callable-being-assigned-to has a "Todo signature", which
should probably accept any left hand side callable/signature.
2025-04-28 16:40:35 +02:00
Dylan 1e8881f9af
[`refurb`] Mark fix as safe for `readlines-in-for` (`FURB129`) (#17644)
This PR promotes the fix applicability of [readlines-in-for
(FURB129)](https://docs.astral.sh/ruff/rules/readlines-in-for/#readlines-in-for-furb129)
to always safe.

In the original PR (https://github.com/astral-sh/ruff/pull/9880), the
author marked the rule as unsafe because Ruff's type inference couldn't
quite guarantee that we had an `IOBase` object in hand. Some false
positives were recorded in the test fixture. However, before the PR was
merged, Charlie added the necessary type inference and the false
positives went away.

According to the [Python
documentation](https://docs.python.org/3/library/io.html#io.IOBase), I
believe this fix is safe for any proper implementation of `IOBase`:

>[IOBase](https://docs.python.org/3/library/io.html#io.IOBase) (and its
subclasses) supports the iterator protocol, meaning that an
[IOBase](https://docs.python.org/3/library/io.html#io.IOBase) object can
be iterated over yielding the lines in a stream. Lines are defined
slightly differently depending on whether the stream is a binary stream
(yielding bytes), or a text stream (yielding character strings). See
[readline()](https://docs.python.org/3/library/io.html#io.IOBase.readline)
below.

and then in the [documentation for
`readlines`](https://docs.python.org/3/library/io.html#io.IOBase.readlines):

>Read and return a list of lines from the stream. hint can be specified
to control the number of lines read: no more lines will be read if the
total size (in bytes/characters) of all lines so far exceeds hint. [...]
>Note that it’s already possible to iterate on file objects using for
line in file: ... without calling file.readlines().

I believe that a careful reading of our [versioning
policy](https://docs.astral.sh/ruff/versioning/#version-changes)
requires that this change be deferred to a minor release - but please
correct me if I'm wrong!
2025-04-28 09:39:55 -05:00
Dylan 152a0b6585
Collect preview lint behaviors in separate module (#17646)
This PR collects all behavior gated under preview into a new module
`ruff_linter::preview` that exposes functions like
`is_my_new_feature_enabled` - just as is done in the formatter crate.
2025-04-28 09:12:24 -05:00
David Peter 92f95ff494
[red-knot] TypedDict: No errors for introspection dunder attributes (#17677)
## Summary

Do not emit errors when accessing introspection dunder attributes such
as `__required_keys__` on `TypedDict`s.
2025-04-28 13:28:43 +02:00
Victor Hugo Gomes ceb2bf1168
[`flake8-pyi`] Ensure `Literal[None,] | Literal[None,]` is not autofixed to `None | None` (`PYI061`) (#17659)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-28 12:23:29 +01:00
David Peter f521358033
[red-knot] No errors for definitions of `TypedDict`s (#17674)
## Summary

Do not emit errors when defining `TypedDict`s:

```py
from typing_extensions import TypedDict

# No error here
class Person(TypedDict):
    name: str
    age: int | None

# No error for this alternative syntax
Message = TypedDict("Message", {"id": int, "content": str})
```

## Ecosystem analysis

* Removes ~ 450 false positives for `TypedDict` definitions.
* Changes a few diagnostic messages.
* Adds a few (< 10) false positives, for example:
  ```diff
+ error[lint:unresolved-attribute]
/tmp/mypy_primer/projects/hydra-zen/src/hydra_zen/structured_configs/_utils.py:262:5:
Type `Literal[DataclassOptions]` has no attribute `__required_keys__`
+ error[lint:unresolved-attribute]
/tmp/mypy_primer/projects/hydra-zen/src/hydra_zen/structured_configs/_utils.py:262:42:
Type `Literal[DataclassOptions]` has no attribute `__optional_keys__`
  ```
* New true positive

4f8263cd7f/corporate/lib/remote_billing_util.py (L155-L157)
  ```diff
+ error[lint:invalid-assignment]
/tmp/mypy_primer/projects/zulip/corporate/lib/remote_billing_util.py:155:5:
Object of type `RemoteBillingIdentityDict | LegacyServerIdentityDict |
None` is not assignable to `LegacyServerIdentityDict | None`
  ```

## Test Plan

New Markdown tests
2025-04-28 13:13:28 +02:00
Micha Reiser dbc137c951
[red-knot] Use 101 exit code when there's at least one diagnostic with severity 'fatal' (#17640) 2025-04-28 10:03:14 +02:00
Victor Hugo Gomes 826b2c9ff3
[`pycodestyle`] Fix duplicated diagnostic in `E712` (#17651) 2025-04-28 08:31:16 +01:00
jie211 a3e55cfd8f
[airflow] fix typos `AIR312` (#17673) 2025-04-28 08:31:41 +02:00
justin d2246278e6
[red-knot] Don't ignore hidden files by default (#17655) 2025-04-28 08:21:11 +02:00
Micha Reiser 1bdb22c139
[red-knot] Fix offset handling in playground for 2-code-point UTF16 characters (#17520) 2025-04-27 11:44:55 +01:00
Micha Reiser 1c65e0ad25
Split `SourceLocation` into `LineColumn` and `SourceLocation` (#17587) 2025-04-27 11:27:33 +01:00
justin 4443f6653c
[red-knot] Add --respect-ignore-files flag (#17645)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-27 10:55:41 +01:00
Vasco Schiavo b0d475f353
[`ruff`] add fix safety section (`RUF027`) (#17485)
The PR add the `fix safety` section for rule `RUF027` (#15584 ).

Actually, I have an example of a false positive. Should I include it in
the` fix safety` section?

---------

Co-authored-by: Dylan <dylwil3@gmail.com>
2025-04-26 16:43:53 -05:00
Vasco Schiavo b578a828ef
[`ruff`] add fix safety section (`RUF005`) (#17484)
The PR add the `fix safety` section for rule `RUF005` (#15584 ).

---------

Co-authored-by: Dylan <dylwil3@gmail.com>
2025-04-26 16:43:02 -05:00
Vasco Schiavo 64ba39a385
[`flynt`] add fix safety section (`FLY002`) (#17496)
The PR add the fix safety section for rule `FLY002` (#15584 )

The motivation for the content of the fix safety section is given by the
following example

```python
foo = 1
bar = [2, 3]

try:
    result_join = " ".join((foo, bar))
    print(f"Join result: {result_join}")
except TypeError as e:
    print(f"Join error: {e}")
```

which print `Join error: sequence item 0: expected str instance, int
found`

But after the fix is applied, we have

```python
foo = 1
bar = [2, 3]

try:
    result_join = f"{foo} {bar}"
    print(f"Join result: {result_join}")
except TypeError as e:
    print(f"Join error: {e}")
```

which print `Join result: 1 [2, 3]`

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-04-26 16:00:01 +00:00
Hans a4e225ee8a
[`flake8-async`] Add fix safety section (`ASYNC116`) (#17497)
## Summary

This PR add the `fix safety` section for rule `ASYNC116` in
`long_sleep_not_forever.rs` for #15584

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-04-26 10:40:51 -05:00
Vasco Schiavo 45d0634b01
[`pydocstyle`] add fix safety section (`D200`) (#17502)
The PR add the fix safety section for rule `D200` (#15584 )
2025-04-26 08:59:05 -05:00
Vasco Schiavo 4bcf1778fa
[`ruff`] add fix safety section (`RUF057`) (#17483)
The PR add the `fix safety` section for rule `RUF057` (#15584 )
2025-04-26 06:58:52 -05:00
Micha Reiser 6044f04137
Revert "[red-knot] Add --respect-ignore-files flag (#17569)" (#17642) 2025-04-26 10:30:50 +00:00
justin 2e95475f57
[red-knot] Add --respect-ignore-files flag (#17569)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-26 10:02:03 +00:00
Micha Reiser cfa1505068
[red-knot] Fix CLI hang when a dependent query panics (#17631) 2025-04-26 06:28:45 +00:00
Dhruv Manilawala 0251679f87
[red-knot] Add new property tests for subtyping with "bottom" callable (#17635)
## Summary

I remember we discussed about adding this as a property tests so here I
am.

## Test Plan

```console
❯ QUICKCHECK_TESTS=10000000 cargo test --locked --release --package red_knot_python_semantic -- --ignored types::property_tests::stable::bottom_callable_is_subtype_of_all_fully_static_callable
    Finished `release` profile [optimized] target(s) in 0.10s
     Running unittests src/lib.rs (target/release/deps/red_knot_python_semantic-e41596ca2dbd0e98)
running 1 test
test types::property_tests::stable::bottom_callable_is_subtype_of_all_fully_static_callable ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 233 filtered out; finished in 30.91s
```
2025-04-26 03:58:13 +05:30
Douglas Creager 6ab32a7746
[red-knot] Create generic context for generic classes lazily (#17617)
As discussed today, this is needed to handle legacy generic classes
without having to infer the types of the class's explicit bases eagerly
at class construction time. Pulling this out into a separate PR so
there's a smaller diff to review.

This also makes our representation of generic classes and functions more
consistent — before, we had separate Rust types and enum variants for
generic/non-generic classes, but a single type for generic functions.
Now we each a single (respective) type for each.

There were very few places we were differentiation between generic and
non-generic _class literals_, and these are handled now by calling the
(salsa cached) `generic_context` _accessor function_.

Note that _`ClassType`_ is still an enum with distinct variants for
non-generic classes and specialized generic classes.
2025-04-25 14:10:03 -04:00
Andrew Gallant bc0a5aa409 ruff_db: add tests for annotations with no ranges
... and fix the case where an annotation with a `Span` but no
`TextRange` or message gets completely dropped.
2025-04-25 13:25:20 -04:00
Wei Lee aba21a5d47
[`airflow`] Extend `AIR301` rule (#17598)
## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Add "airflow.operators.python.get_current_context" →
"airflow.sdk.get_current_context" rule

## Test Plan

<!-- How was it tested? -->

the test fixture has been updated accordingly
2025-04-25 12:49:32 -04:00
Wei Lee b6281a8805
[`airflow`] update existing `AIR302` rules with better suggestions (#17542)
## Summary

Even though the original suggestion works, they've been removed in later
version and is no longer the best practices.

e.g., many sql realted operators have been removed and are now suggested
to use SQLExecuteQueryOperator instead

## Test Plan

The existing test fixtures have been updated
2025-04-25 12:44:28 -04:00
Andrew Gallant 049280a3bc red_knot_project: sort diagnostics from checking files
Previously, we could iterate over files in an unspecified order (via
`HashSet` iteration) and we could accumulate diagnostics from files in
an unspecified order (via parallelism).

Here, we change the status quo so that diagnostics collected from files
are sorted after checking is complete. For now, we sort by severity
(with higher severity diagnostics appearing first) and then by
diagnostic ID to give a stable ordering.

I'm not sure if this is the best ordering.
2025-04-25 12:38:31 -04:00
Carl Meyer fa88989ef0
[red-knot] fix detecting a metaclass on a not-explicitly-specialized generic base (#17621)
## Summary

After https://github.com/astral-sh/ruff/pull/17620 (which this PR is
based on), I was looking at other call sites of `Type::into_class_type`,
and I began to feel that _all_ of them were currently buggy due to
silently skipping unspecialized generic class literal types (though in
some cases the bug hadn't shown up yet because we don't understand
legacy generic classes from typeshed), and in every case they would be
better off if an unspecialized generic class literal were implicitly
specialized with the default specialization (which is the usual Python
typing semantics for an unspecialized reference to a generic class),
instead of silently skipped.

So I changed the method to implicitly apply the default specialization,
and added a test that previously failed for detecting metaclasses on an
unspecialized generic base.

I also renamed the method to `to_class_type`, because I feel we have a
strong naming convention where `Type::into_foo` is always a trivial
`const fn` that simply returns `Some()` if the type is of variant `Foo`
and `None` otherwise. Even the existing method (with it handling both
`GenericAlias` and `ClassLiteral`, and distinguishing kinds of
`ClassLiteral`) was stretching this convention, and the new version
definitely breaks that envelope.

## Test Plan

Added a test that failed before this PR.
2025-04-25 06:55:54 -07:00
Carl Meyer 4c3f389598
[red-knot] fix inheritance-cycle detection for generic classes (#17620)
## Summary

The `ClassLiteralType::inheritance_cycle` method is intended to detect
inheritance cycles that would result in cyclic MROs, emit a diagnostic,
and skip actually trying to create the cyclic MRO, falling back to an
"error" MRO instead with just `Unknown` and `object`.

This method didn't work properly for generic classes. It used
`fully_static_explicit_bases`, which filter-maps `explicit_bases` over
`Type::into_class_type`, which returns `None` for an unspecialized
generic class literal. So in a case like `class C[T](C): ...`, because
the explicit base is an unspecialized generic, we just skipped it, and
failed to detect the class as cyclically defined.

Instead, iterate directly over all `explicit_bases`, and explicitly
handle both the specialized (`GenericAlias`) and unspecialized
(`ClassLiteral`) cases, so that we check all bases and correctly detect
cyclic inheritance.

## Test Plan

Added mdtests.
2025-04-25 06:55:00 -07:00
Brent Westbrook 6d3b1d13d6
[`pylint`] Detect `global` declarations in module scope (`PLE0118`) (#17411)
Summary
--

While going through the syntax errors in [this comment], I was surprised
to see the error `name 'x' is assigned to before global declaration`,
which corresponds to [load-before-global-declaration (PLE0118)] and has
also been reimplemented as a syntax error (#17135). However, it looks
like neither of the implementations consider `global` declarations in
the top-level module scope, which is a syntax error in CPython:

```python
# try.py
x = None
global x
```

```shell
> python -m compileall -f try.py
Compiling 'try.py'...
***   File "try.py", line 2
    global x
    ^^^^^^^^
SyntaxError: name 'x' is assigned to before global declaration
```

I'm not sure this is the best or most elegant solution, but it was a
quick fix that passed all of our tests.

Test Plan
--

New PLE0118 test case.

[this comment]:
https://github.com/astral-sh/ruff/issues/7633#issuecomment-1740424031
[load-before-global-declaration (PLE0118)]:
https://docs.astral.sh/ruff/rules/load-before-global-declaration/#load-before-global-declaration-ple0118
2025-04-25 08:37:16 -04:00
Max Mynter 3f84e75e20
Add Semantic Error Test for LateFutureImport (#17612)
Adresses a question in #17526.

## Summary
Adds a syntax error test for `__future__` import not at top of file. 

## Question: 
Is this a redundant with
8d2c79276d/crates/ruff_linter/resources/test/fixtures/pyflakes/F404_0.py (L1-L8)
and
8d2c79276d/crates/ruff_linter/resources/test/fixtures/pyflakes/F404_1.py (L1-L5)

which test pyflake `F404`?
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan
This is a test
<!-- How was it tested? -->
2025-04-25 08:32:57 -04:00
Carl Meyer afc18ff1a1
[red-knot] change TypeVarInstance to be interned, not tracked (#17616)
## Summary

Tracked structs have some issues with fixpoint iteration in Salsa, and
there's not actually any need for this to be tracked, it should be
interned like most of our type structs.

The removed comment was probably never correct (in that we could have
disambiguated sufficiently), and is definitely not relevant now that
`TypeVarInstance` also holds its `Definition`.

## Test Plan

Existing tests.
2025-04-24 14:52:25 -07:00
Dhruv Manilawala f1a539dac6
[red-knot] Special case `@final`, `@override` (#17608)
## Summary

This PR adds special-casing for `@final` and `@override` decorator for a
similar reason as https://github.com/astral-sh/ruff/pull/17591 to
support the invalid overload check.

Both `final` and `override` are identity functions which can be removed
once `TypeVar` support is added.
2025-04-25 03:15:23 +05:30
Carl Meyer ef0343189c
[red-knot] add TODO comment in specialization code (#17615)
## Summary

As promised, this just adds a TODO comment to document something we
discussed today that should probably be improved at some point, but
isn't a priority right now (since it's an issue that in practice would
only affect generic classes with both `__init__` and `__new__` methods,
where some typevar is bound to `Unknown` in one and to some other type
in another.)
2025-04-24 14:41:19 -07:00
Vasco Schiavo 4eecc40110
[`semantic-syntax-errors`] test for `LoadBeforeGlobalDeclaration` - ruff linter (#17592)
Hey @ntBre 

just one easy case to see if I understood the issue #17526 

Let me know if is this what you had in mind.
2025-04-24 16:14:33 -04:00
Abhijeet Prasad Bodas cf59cee928
[syntax-errors] `nonlocal` declaration at module level (#17559)
## Summary

Part of #17412

Add a new compile-time syntax error for detecting `nonlocal`
declarations at a module level.

## Test Plan

- Added new inline tests for the syntax error
- Updated existing tests for `nonlocal` statement parsing to be inside a
function scope

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-04-24 16:11:46 -04:00
Wei Lee 538393d1f3
[`airflow`] Apply auto fix to cases where name has been changed in Airflow 3 (`AIR311`) (#17571)
## Summary

Apply auto fix to cases where the name has been changed in Airflow 3
(`AIR311`)

## Test Plan

The test features has been updated
2025-04-24 15:48:54 -04:00
Brent Westbrook 92ecfc908b
[syntax-errors] Make `async-comprehension-in-sync-comprehension` more specific (#17460)
## Summary

While adding semantic error support to red-knot, I noticed duplicate
diagnostics for code like this:

```py
# error: [invalid-syntax] "cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.9 (syntax was added in 3.11)"
# error: [invalid-syntax] "`asynchronous comprehension` outside of an asynchronous function"
 [reveal_type(x) async for x in AsyncIterable()]
```

Beyond the duplication, the first error message doesn't make much sense
because this syntax is _not_ allowed on Python 3.11 either.

To fix this, this PR renames the
`async-comprehension-outside-async-function` semantic syntax error to
`async-comprehension-in-sync-comprehension` and fixes the rule to avoid
applying outside of sync comprehensions at all.

## Test Plan

New linter test demonstrating the false positive. The mdtests from my red-knot 
PR also reflect this change.
2025-04-24 15:45:54 -04:00
Dylan f7b48510b5
Bump 0.11.7 (#17613) 2025-04-24 13:06:38 -05:00
Dhruv Manilawala 9937064761
[red-knot] Use iterative approach to collect overloads (#17607)
## Summary

This PR updates the `to_overloaded` method to use an iterative approach
instead of a recursive one.

Refer to
https://github.com/astral-sh/ruff/pull/17585#discussion_r2056804587 for
context.

The main benefit here is that it avoids calling the `to_overloaded`
function in a recursive manner which is a salsa query. So, this is a bit
hand wavy but we should also see less memory used because the cache will
only contain a single entry which should be the entire overload chain.
Previously, the recursive approach would mean that each of the function
involved in an overload chain would have a cache entry. This reduce in
memory shouldn't be too much and I haven't looked at the actual data for
it.

## Test Plan

Existing test cases should pass.
2025-04-24 22:23:50 +05:30
Andrew Gallant 8d2c79276d red_knot_python_semantic: avoid Rust's screaming snake case convention in mdtest 2025-04-24 11:43:01 -04:00
Andrew Gallant 0f47810768 red_knot_python_semantic: improve diagnostics for unsupported boolean conversions
This mostly only improves things for incorrect arguments and for an
incorrect return type. It doesn't do much to improve the case where
`__bool__` isn't callable and leaves the union/other cases untouched
completely.

I picked this one because, at first glance, this _looked_ like a lower
hanging fruit. The conceptual improvement here is pretty
straight-forward: add annotations for relevant data. But it took me a
bit to figure out how to connect all of the pieces.
2025-04-24 11:43:01 -04:00
Andrew Gallant eb1d2518c1 red_knot_python_semantic: add "return type span" helper method
This is very similar to querying for the span of a parameter
in a function definition, but instead we look for the span of
a return type.
2025-04-24 11:43:01 -04:00
Andrew Gallant a45a0a92bd red_knot_python_semantic: move parameter span helper method
I wanted to use this method in other places, so I moved it
to what appears to be a God-type. I also made it slightly
more versatile: callers can ask for the entire parameter list
by omitting a specific parameter index.
2025-04-24 11:43:01 -04:00
Andrew Gallant 43bd043755 ruff_db: add a `From` impl for `FileRange` to `Span`
These types are almost equivalent. The only difference
is that a `Span`'s range is optional.
2025-04-24 11:43:01 -04:00
Andrew Gallant 9a54ee3a1c red_knot_python_semantic: add snapshot tests for unsupported boolean conversions
This just captures the status quo before we try to improve them.
2025-04-24 11:43:01 -04:00
Carl Meyer 25c3be51d2
[red-knot] simplify != narrowing (#17610)
## Summary

Follow-up from review comment in
https://github.com/astral-sh/ruff/pull/17567#discussion_r2058649527

## Test Plan

Existing tests.
2025-04-24 15:11:45 +00:00
Matthew Mckee e71f3ed2c5
[red-knot] Update `==` and `!=` narrowing (#17567)
## Summary

Historically we have avoided narrowing on `==` tests because in many
cases it's unsound, since subclasses of a type could compare equal to
who-knows-what. But there are a lot of types (literals and unions of
them, as well as some known instances like `None` -- single-valued
types) whose `__eq__` behavior we know, and which we can safely narrow
away based on equality comparisons.

This PR implements equality narrowing in the cases where it is sound.
The most elegant way to do this (and the way that is most in-line with
our approach up until now) would be to introduce new Type variants
`NeverEqualTo[...]` and `AlwaysEqualTo[...]`, and then implement all
type relations for those variants, narrow by intersection, and let union
and intersection simplification sort it all out. This is analogous to
our existing handling for `AlwaysFalse` and `AlwaysTrue`.

But I'm reluctant to add new `Type` variants for this, mostly because
they could end up un-simplified in some types and make types even more
complex. So let's try this approach, where we handle more of the
narrowing logic as a special case.

## Test Plan

Updated and added tests.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
Co-authored-by: Carl Meyer <carl@oddbird.net>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-24 07:56:39 -07:00
Carl Meyer ac6219ec38
[red-knot] fix collapsing literal and its negation to object (#17605)
## Summary

Another follow-up to the unions-of-large-literals optimization. Restore
the behavior that e.g. `Literal[""] | ~Literal[""]` collapses to
`object`.

## Test Plan

Added mdtests.
2025-04-24 13:55:05 +00:00
Alex Waygood e93fa7062c
[red-knot] Add more tests for protocols (#17603) 2025-04-24 13:11:31 +01:00
Alex Waygood 21fd28d713
[red-knot] Ban direct instantiations of `Protocol` classes (#17597) 2025-04-24 09:31:35 +00:00
Max Mynter a01f25107a
[`pyupgrade`] Preserve parenthesis when fixing native literals containing newlines (`UP018`) (#17220) 2025-04-24 08:48:02 +02:00
camper42 48a85c4ed4
[`airflow`] fix typos (`AIR302`, `AIR312`) (#17574) 2025-04-24 08:06:32 +02:00
Dhruv Manilawala 1796ca97d5
[red-knot] Special case `@abstractmethod` for function type (#17591)
## Summary

This is required because otherwise the inferred type is not going to be
`Type::FunctionLiteral` but a todo type because we don't recognize
`TypeVar` yet:

```py
_FuncT = TypeVar("_FuncT", bound=Callable[..., Any])

def abstractmethod(funcobj: _FuncT) -> _FuncT: ...
```

This is mainly required to raise diagnostic when only some (and not all)
`@overload`-ed functions are decorated with `@abstractmethod`.
2025-04-24 03:54:52 +05:30
Alex Waygood e897f37911
[red-knot] Emit diagnostics for isinstance() and issubclass() calls where a non-runtime-checkable protocol is the second argument (#17561) 2025-04-23 21:40:23 +00:00
Alex Waygood 00e73dc331
[red-knot] Infer the members of a protocol class (#17556) 2025-04-23 21:36:12 +00:00
Dhruv Manilawala 7b6222700b
[red-knot] Add `FunctionType::to_overloaded` (#17585)
## Summary

This PR adds a new method `FunctionType::to_overloaded` which converts a
`FunctionType` into an `OverloadedFunction` which contains all the
`@overload`-ed `FunctionType` and the implementation `FunctionType` if
it exists.

There's a big caveat here (it's the way overloads work) which is that
this method can only "see" all the overloads that comes _before_ itself.
Consider the following example:

```py
from typing import overload

@overload
def foo() -> None: ...
@overload
def foo(x: int) -> int: ...
def foo(x: int | None) -> int | None:
	return x
```

Here, when the `to_overloaded` method is invoked on the
1. first `foo` definition, it would only contain a single overload which
is itself and no implementation.
2. second `foo` definition, it would contain both overloads and still no
implementation
3. third `foo` definition, it would contain both overloads and the
implementation which is itself

### Usages

This method will be used in the logic for checking invalid overload
usages. It can also be used for #17541.

## Test Plan

Make sure that existing tests pass.
2025-04-24 02:57:05 +05:30
Brent Westbrook bfc1650198
[red-knot] Add mdtests for `global` statement (#17563)
## Summary

This is a first step toward `global` support in red-knot (#15385). I
went through all the matches for `global` in the `mypy/test-data`
directory, but I didn't find anything too interesting that wasn't
already covered by @carljm's suggestions on Discord. I still pulled in a
couple of cases for a little extra variety. I also included a section
from the
[PLE0118](https://docs.astral.sh/ruff/rules/load-before-global-declaration/)
tests in ruff that will become syntax errors once #17463 is merged and
we handle `global` statements.

I don't think I figured out how to use `@Todo` properly, so please let
me know if I need to fix that. I hope this is a good start to the test
suite otherwise.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-23 17:18:42 -04:00
Brent Westbrook d5410ef9fe
[syntax-errors] Make duplicate parameter names a semantic error (#17131)
Status
--

This is a pretty minor change, but it was breaking a red-knot mdtest
until #17463 landed. Now this should close #11934 as the last syntax
error being tracked there!

Summary
--

Moves `Parser::validate_parameters` to
`SemanticSyntaxChecker::duplicate_parameter_name`.

Test Plan
--

Existing tests, with `## Errors` replaced with `## Semantic Syntax
Errors`.
2025-04-23 15:45:51 -04:00