Commit Graph

236 Commits

Author SHA1 Message Date
Alex Waygood c816542704
[red-knot] Fix some instance-attribute TODOs around `ModuleType` (#15974) 2025-02-05 15:33:37 +00:00
Alex Waygood 2ebb5e8d4b
[red-knot] Make `Symbol::or_fall_back_to()` lazy (#15943) 2025-02-05 14:51:02 +00:00
David Peter eb08345fd5
[red-knot] Extend instance/class attribute tests (#15959)
## Summary

In preparation for creating some (sub) issues for
https://github.com/astral-sh/ruff/issues/14164, I'm trying to document
the current behavior (and a bug) a bit better.
2025-02-05 12:45:00 +01:00
Mike Perlov e15419396c
[red-knot] Fix Stack overflow in Type::bool (#15843)
## Summary

This PR adds `Type::call_bound` method for calls that should follow
descriptor protocol calling convention. The PR is intentionally shallow
in scope and only fixes #15672

Couple of obvious things that weren't done:

* Switch to `call_bound` everywhere it should be used
* Address the fact, that red_knot resolves `__bool__ = bool` as a Union,
which includes `Type::Dynamic` and hence fails to infer that the
truthiness is always false for such a class (I've added a todo comment
in mdtests)
* Doesn't try to invent a new type for descriptors, although I have a
gut feeling it may be more convenient in the end, instead of doing
method lookup each time like I did in `call_bound`

## Test Plan

* extended mdtests with 2 examples from the issue
* cargo neatest run
2025-02-04 12:40:07 -08:00
Douglas Creager 444b055cec
[red-knot] Use ternary decision diagrams (TDDs) for visibility constraints (#15861)
We now use ternary decision diagrams (TDDs) to represent visibility
constraints. A TDD is just like a BDD ([_binary_ decision
diagram](https://en.wikipedia.org/wiki/Binary_decision_diagram)), but
with "ambiguous" as an additional allowed value. Unlike the previous
representation, TDDs are strongly normalizing, so equivalent ternary
formulas are represented by exactly the same graph node, and can be
compared for equality in constant time.

We currently have a slight 1-3% performance regression with this in
place, according to local testing. However, we also have a _5× increase_
in performance for pathological cases, since we can now remove the
recursion limit when we evaluate visibility constraints.

As follow-on work, we are now closer to being able to remove the
`simplify_visibility_constraint` calls in the semantic index builder. In
the vast majority of cases, we now see (for instance) that the
visibility constraint after an `if` statement, for bindings of symbols
that weren't rebound in any branch, simplifies back to `true`. But there
are still some cases we generate constraints that are cyclic. With
fixed-point cycle support in salsa, or with some careful analysis of the
still-failing cases, we might be able to remove those.
2025-02-04 14:32:11 -05:00
David Peter 24c1cf71cb
[red-knot] Use unambiguous invalid-syntax-construct for suppression comment test (#15933)
## Summary

I experimented with [not trimming trailing newlines in code
snippets](https://github.com/astral-sh/ruff/pull/15926#discussion_r1940992090),
but since came to the conclusion that the current behavior is better
because otherwise, there is no way to write snippets without a trailing
newline at all. And when you copy the code from a Markdown snippet in
GitHub, you also don't get a trailing newline.

I was surprised to see some test failures when I played with this
though, and decided to make this test independent from this
implementation detail.
2025-02-04 15:24:50 +01:00
InSync 11cfe2ea8a
[red-knot] Enforce specifying paths for mdtest code blocks in a separate preceding line (#15890)
## Summary

Resolves #15695, rework of #15704.

This change modifies the Mdtests framework so that:

* Paths must now be specified in a separate preceding line:

	`````markdown
	`a.py`:

	```py
	x = 1
	```
	`````

If the path of a file conflicts with its `lang`, an error will be
thrown.

* Configs are no longer accepted. The pattern still take them into
account, however, to avoid "Unterminated code block" errors.
* Unnamed files are now assigned unique, `lang`-respecting paths
automatically.

Additionally, all legacy usages have been updated.

## Test Plan

Unit tests and Markdown tests.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-02-04 08:27:17 +01:00
David Peter 102c2eec12
[red-knot] Implicit instance attributes (#15811)
## Summary

Add support for implicitly-defined instance attributes, i.e. support
type inference for cases like this:
```py
class C:
    def __init__(self) -> None:
        self.x: int = 1
        self.y = None

reveal_type(C().x)  # int
reveal_type(C().y)  # Unknown | None
```

## Benchmarks

Codspeed reports no change in a cold-cache benchmark, and a -1%
regression in the incremental benchmark. On `black`'s `src` folder, I
don't see a statistically significant difference between the branches:

| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|:---|---:|---:|---:|---:|
| `./red_knot_main check --project /home/shark/black/src` | 133.7 ± 9.5 | 126.7 | 164.7 | 1.01 ± 0.08 |
| `./red_knot_feature check --project /home/shark/black/src` | 132.2 ± 5.1 | 118.1 | 140.9 | 1.00 |

## Test Plan

Updated and new Markdown tests
2025-02-03 19:34:23 +01:00
Dhruv Manilawala d082c1b202
[red-knot] Add missing imports in mdtests (#15869)
## Summary

Related to #15848, this PR adds the imports explicitly as we'll now flag
these symbols as undefined.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-03 09:27:29 +00:00
David Peter 451f251a31
[red-knot] Clarify behavior when redeclaring base class attributes (#15826)
# Summary

Clarify the behavior regarding re-declaration of attributes from base
classes following [this
discussion](https://github.com/astral-sh/ruff/pull/15808#discussion_r1934236095)
2025-01-30 14:49:23 +01:00
Alex Waygood 3125332ec1
[red-knot] Format mdtest snippets with the latest version of black (#15819) 2025-01-29 23:05:43 +00:00
Douglas Creager 15d886a502
[red-knot] Consider all definitions after terminal statements unreachable (#15676)
`FlowSnapshot` now tracks a `reachable` bool, which indicates whether we
have encountered a terminal statement on that control flow path. When
merging flow states together, we skip any that have been marked
unreachable. This ensures that bindings that can only be reached through
unreachable paths are not considered visible.

## Test Plan

The new mdtests failed (with incorrect `reveal_type` results, and
spurious `possibly-unresolved-reference` errors) before adding the new
visibility constraints.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-01-29 14:06:57 -05:00
David Peter 0f1035b930
[red-knot] Extend instance-attribute tests (#15808)
## Summary

When we discussed the plan on how to proceed with instance attributes,
we said that we should first extend our research into the behavior of
existing type checkers. The result of this research is summarized in the
newly added / modified tests in this PR. The TODO comments align with
existing behavior of other type checkers. If we deviate from the
behavior, it is described in a comment.
2025-01-29 14:06:32 +01:00
David Peter ca53eefa6f
[red-knot] Do not use explicit `knot_extensions.Unknown` declaration (#15787)
## Summary

Do not use an explict `knot_extensions.Unknown` declaration, as per
[this
comment](https://github.com/astral-sh/ruff/pull/15766#discussion_r1930997592).
Instead, use an undefined name to achieve the same effect.
2025-01-28 17:18:22 +01:00
David Peter 2ef94e5f3e
[red-knot] Document public symbol type inferece (#15766)
## Summary

Adds a slightly more comprehensive documentation of our behavior
regarding type inference for public uses of symbols. In particular:

- What public type do we infer for `x: int = any()`?
- What public type do we infer for `x: Unknown = 1`?
2025-01-27 10:52:13 +01:00
Alex Waygood c824140fa8
[red-knot] Ensure differently ordered unions are considered equivalent when they appear inside tuples inside top-level intersections (#15743) 2025-01-25 18:19:28 +00:00
Alex Waygood f85ea1bf46
[red-knot] Ensure differently ordered unions and intersections are understood as equivalent even inside arbitrarily nested tuples (#15740)
## Summary

On `main`, red-knot:
- Considers `P | Q` equivalent to `Q | P`
- Considered `tuple[P | Q]` equivalent to `tuple[Q | P]`
- Considers `tuple[P | tuple[P | Q]]` equivalent to `tuple[tuple[Q | P]
| P]`
- ‼️ Does _not_ consider `tuple[tuple[P | Q]]` equivalent to
`tuple[tuple[Q | P]]`

The key difference for the last one of these is that the union appears
inside a tuple that is directly nested inside another tuple.

This PR fixes this so that differently ordered unions are considered
equivalent even when they appear inside arbitrarily nested tuple types.

## Test Plan

- Added mdtests that fails on `main`
- Checked that all property tests continue to pass with this PR
2025-01-25 16:39:07 +00:00
Micha Reiser 4e3982cf95
[red-knot] Add `--ignore`, `--warn`, and `--error` CLI arguments (#15689) 2025-01-24 16:20:15 +01:00
David Peter 1feb3cf41a
[red-knot] Use `Unknown | T_inferred` for undeclared public symbols (#15674)
## Summary

Use `Unknown | T_inferred` as the type for *undeclared* public symbols.

## Test Plan

- Updated existing tests
- New test for external `__slots__` modifications.
- New tests for external modifications of public symbols.
2025-01-24 12:47:48 +01:00
David Peter 15394a8028
[red-knot] MDTests: Do not depend on precise public-symbol type inference (#15691)
## Summary

Another small PR to focus #15674 solely on the relevant changes. This
makes our Markdown tests less dependent on precise types of public
symbols, without actually changing anything semantically in these tests.

Best reviewed using ignore-whitespace-mode.

## Test Plan

Tested these changes on `main` and on the branch from #15674.
2025-01-23 13:51:33 +00:00
David Peter 0173738eef
[red-knot] Port comprehension tests to Markdown (#15688)
## Summary

Port comprehension tests from Rust to Markdown

I don' think the remaining tests in `infer.rs` should be ported to
Markdown, maybe except for the incremental-checking tests when (if ever)
we have support for that in the MD tests.


closes #13696
2025-01-23 12:49:30 +00:00
David Peter 1e790d3885
[red-knot] Port 'deferred annotations' unit tests to Markdown (#15686)
## Summary

- Port "deferred annotations" unit tests to Markdown
- Port `implicit_global_in_function` unit test to Markdown
- Removed `resolve_method` and `local_inference` unit tests. These seem
  like relics from a time where type inference was in it's early stages.
  There is no way that these tests would fail today without lots of other
  things going wrong as well.

part of #13696
based on #15683 

## Test Plan

New MD tests for existing Rust unit tests.
2025-01-23 11:45:05 +00:00
David Peter 7855f03735
[red-knot] Support custom typeshed Markdown tests (#15683)
## Summary

- Add feature to specify a custom typeshed from within Markdown-based
  tests
- Port "builtins" unit tests from `infer.rs` to Markdown tests, part of
  #13696

## Test Plan

- Tests for the custom typeshed feature
- New Markdown tests for deleted Rust unit tests
2025-01-23 12:36:38 +01:00
David Peter 1ecd97855e
[red-knot] Add test for nested attribute access (#15684)
## Summary

Add a new test for attribute accesses in case of nested modules /
classes. Resolves this comment:

https://github.com/astral-sh/ruff/pull/15613#discussion_r1925637561

## Test Plan

New MD test.
2025-01-23 10:26:34 +01:00
Alex Waygood b4877f1661
[red-knot] Ensure a gradual type can always be assigned to itself (#15675) 2025-01-22 16:01:13 +00:00
David Peter 13e7afca42
[red-knot] Improved error message for attribute-assignments (#15668)
## Summary

Slightly improved error message for attribute assignments.
2025-01-22 11:04:38 +00:00
David Peter f349dab4fc
[red-knot] Invalid assignments to attributes (#15613)
## Summary

Raise "invalid-assignment" diagnostics for incorrect assignments to
attributes, for example:

```py
class C:
    var: str = "a"

C.var = 1  # error: "Object of type `Literal[1]` is not assignable to `str`"
```

closes #15456 

## Test Plan

- Updated test assertions
- New test for assignments to module-attributes
2025-01-22 10:42:47 +01:00
Alex Waygood 187a358d7a
[red-knot] Heterogeneous tuple types with differently ordered (but equivalent) unions at the same index should be considered equivalent (#15637) 2025-01-21 12:51:20 +00:00
wooly18 f82ef32e53
[`red-knot`] No `cyclic-class-def` diagnostics for subclasses of cyclic classes (#15561)
Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-01-20 13:35:29 +00:00
David Peter 4eb465ee95
[red-knot] Move `type_alias_types` test to Markdown (#15607)
## Summary

Move `type_alias_types` test to Markdown

## Test Plan

New MD test
2025-01-20 09:55:54 +01:00
David Peter 9725a2d476
[red-knot] More exhaustive disjointness tests (#15606)
## Summary

Mostly just brings the structure/format of the disjointness-tests closer
to what we have for `is_subtype_of` etc.
2025-01-20 09:47:51 +01:00
InSync 975d1457c5
[red-knot] Migrate `is_disjoint_from` unit tests to Markdown tests (#15580)
## Summary

Part of and resolves #15397, built on top of #15579.

## Test Plan

Markdown tests.
2025-01-20 08:42:22 +01:00
Alex Waygood 2b24b3b316
[red-knot] Ensure differently ordered unions and intersections are considered equivalent (#15516) 2025-01-19 16:10:42 +00:00
David Peter fb15da5694
[red-knot] Add support for `typing.ClassVar` (#15550)
## Summary

Add support for `typing.ClassVar`, i.e. emit a diagnostic in this
scenario:
```py
from typing import ClassVar

class C:
    x: ClassVar[int] = 1

c = C()
c.x = 3  # error: "Cannot assign to pure class variable `x` from an instance of type `C`"
```

## Test Plan

- New tests for the `typing.ClassVar` qualifier
- Fixed one TODO in `attributes.md`
2025-01-18 13:51:35 +01:00
InSync 9d845ec8f5
[red-knot] Migrate `is_gradual_equivalent_to` unit tests to Markdown tests (#15563)
## Summary

Part of #15397 and #15516.

## Test Plan

Markdown tests.
2025-01-17 16:48:01 -08:00
Alex Waygood 4328df7226
[red-knot] `type[T]` is disjoint from `type[S]` if the metaclass of `T` is disjoint from the metaclass of `S` (#15547) 2025-01-17 10:41:36 +00:00
David Peter 6771b8ebd2
[red-knot] Pure instance variables declared in class body (#15515)
## Summary

This is a small, tentative step towards the bigger goal of understanding
instance attributes.

- Adds partial support for pure instance variables declared in the class
  body, i.e. this case:
  ```py
  class C:
      variable1: str = "a"
      variable2 = "b"

  reveal_type(C().variable1)  # str
  reveal_type(C().variable2)  # Unknown | Literal["b"]
  ```
- Adds `property` as a known class to query for `@property` decorators
- Splits up various `@Todo(instance attributes)` cases into
  sub-categories.

## Test Plan

Modified existing MD tests.
2025-01-17 10:48:20 +01:00
Alex Waygood 3950b00ee4
[red-knot] Implement disjointness for Instance types where the underlying class is `@final` (#15539)
## Summary

Closes https://github.com/astral-sh/ruff/issues/15508

For any two instance types `T` and `S`, we know they are disjoint if
either `T` is final and `T` is not a subclass of `S` or `S` is final and
`S` is not a subclass of `T`.

Correspondingly, for any two types `type[T]` and `S` where `S` is an
instance type, `type[T]` can be said to be disjoint from `S` if `S` is
disjoint from `U`, where `U` is the type that represents all instances
of `T`'s metaclass.

And a heterogeneous tuple type can be said to be disjoint from an
instance type if the instance type is disjoint from `tuple` (a type
representing all instances of the `tuple` class at runtime).

## Test Plan

- A new mdtest added. Most of our `is_disjoint_from()` tests are not
written as mdtests just yet, but it's pretty hard to test some of these
edge cases from a Rust unit test!
- Ran `QUICKCHECK_TESTS=1000000 cargo test --release -p
red_knot_python_semantic -- --ignored types::property_tests::stable`

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-01-16 23:48:52 +00:00
InSync 2e6729d900
[red-knot] Migrate `bool`/`str`/`repr` unit tests to Markdown tests (#15534)
## Summary

Part of #15397.

## Test Plan

Markdown tests.
2025-01-16 11:21:56 -08:00
InSync 6f0b66278f
[red-knot] Migrate `is_fully_static`/`is_single_valued`/`is_singleton` unit tests to Markdown tests (#15533)
## Summary

Part of #15397.

## Test Plan

Markdown tests.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-16 07:40:41 -08:00
Shaygan Hooshyari cf4ab7cba1
Parse triple quoted string annotations as if parenthesized (#15387)
## Summary

Resolves #9467 

Parse quoted annotations as if the string content is inside parenthesis.
With this logic `x` and `y` in this example are equal:

```python
y: """
   int |
   str
"""

z: """(
    int |
    str
)
"""
```

Also this rule only applies to triple
quotes([link](https://github.com/python/typing-council/issues/9#issuecomment-1890808610)).

This PR is based on the
[comments](https://github.com/astral-sh/ruff/issues/9467#issuecomment-2579180991)
on the issue.

I did one extra change, since we don't want any indentation tokens I am
setting the `State::Other` as the initial state of the Lexer.

Remaining work:

- [x] Add a test case for red-knot.
- [x] Add more tests.

## Test Plan

Added a test which previously failed because quoted annotation contained
indentation.
Added an mdtest for red-knot.
Updated previous test.

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-01-16 11:38:15 +05:30
David Peter c034e280a9
[red-knot] Instance attributes: type inference clarifications (#15512)
## Summary

Some clarifications in the instance-attributes tests, mostly regarding
type inference behavior following this discussion:

https://github.com/astral-sh/ruff/pull/15474#discussion_r1917044566
2025-01-15 21:17:55 +01:00
Alex Waygood 49557a9129
[red-knot] Simplify `object` out of intersections (#15511) 2025-01-15 20:06:48 +00:00
David Peter 4f3209a3ec
[red-knot] More comprehensive 'is_subtype_of' tests (#15490)
## Summary

Make the `is_subtype_of` tests a bit easier to understand and
more comprehensive.
2025-01-15 18:33:29 +00:00
Alex Waygood 55a7f72035
[red-knot] Fix more edge cases for intersection simplification with `LiteralString` and `AlwaysTruthy`/`AlwaysFalsy` (#15496) 2025-01-15 15:02:41 +00:00
David Peter 8712438aec
[red-knot] Initial tests for instance attributes (#15474)
## Summary

Adds some initial tests for class and instance attributes, mostly to
document (and discuss) what we want to support eventually. These
tests are not exhaustive yet. The idea is to specify the coarse-grained
behavior first.

Things that we'll eventually want to test:

- Interplay with inheritance
- Support `Final` in addition to `ClassVar`
- Specific tests for `ClassVar`, like making sure that we support things
like `x: Annotated[ClassVar[int], "metadata"]`
- … or making sure that we raise an error here:
  ```py
  class Foo:
      def __init__(self):
          self.x: ClassVar[str] = "x"
  ```
- Add tests for `__new__` in addition to the tests for `__init__`
- Add tests that show that we use the union of types if multiple methods
define the symbol with different types
- Make sure that diagnostics are raised if, e.g., the inferred type of
an assignment within a method does not match the declared type in the
class body.
- https://github.com/astral-sh/ruff/pull/15474#discussion_r1916556284
- Method calls are completely left out for now.
- Same for `@property`
- … and the descriptor protocol

## Test Plan

New Markdown tests

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-15 14:43:41 +00:00
David Peter 3a6238d8c2
[red-knot] Typeshed sync and `sys.platform` fixes (#15492)
## Summary

The next sync of typeshed would have failed without manual changes
anyway, so I'm doing one manual sync + the required changes in our
`sys.platform` tests (which are necessary because of my tiny typeshed PR
here: https://github.com/python/typeshed/pull/13378).

closes #15485 (the next run of the pipeline in two weeks should be fine
as the bug has been fixed upstream)
2025-01-15 11:21:01 +01:00
InSync aefb607405
[red-knot] Migrate `is_equivalent_to` unit tests to Markdown tests (#15470)
## Summary

Part of #15397, built on top of #15469.

## Test Plan

Markdown tests.
2025-01-14 18:57:23 +00:00
Alex Waygood bcf0a715c2
[red-knot] Corrections and improvements to intersection simplification (#15475) 2025-01-14 18:15:38 +00:00
InSync 5ed7b55b15
[red-knot] Migrate `is_subtype_of` unit tests to Markdown tests (#15469)
## Summary

Part of #15397.

## Test Plan

Markdown tests.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-01-14 15:57:24 +01:00