Commit graph

17 commits

Author SHA1 Message Date
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
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
Douglas Creager
5e9259c96c
Don't special-case class instances in binary expression inference (#15161)
Just like in #15045 for unary expressions: In binary expressions, we
were only looking for dunder expressions for `Type::Instance` types. We
had some special cases for coercing the various `Literal` types into
their corresponding `Instance` types before doing the lookup. But we can
side-step all of that by using the existing `Type::to_meta_type` and
`Type::to_instance` methods.
2025-01-06 13:50:20 -05:00
InSync
15fe540251
Improve mdtests style (#14884)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2024-12-10 13:05:51 +00:00
David Peter
47f39ed1a0
[red-knot] Meta data for Type::Todo (#14500)
## Summary

Adds meta information to `Type::Todo`, allowing developers to easily
trace back the origin of a particular `@Todo` type they encounter.

Instead of `Type::Todo`, we now write either `type_todo!()` which
creates a `@Todo[path/to/source.rs:123]` type with file and line
information, or using `type_todo!("PEP 604 unions not supported")`,
which creates a variant with a custom message.

`Type::Todo` now contains a `TodoType` field. In release mode, this is
just a zero-sized struct, in order not to create any overhead. In debug
mode, this is an `enum` that contains the meta information.

`Type` implements `Copy`, which means that `TodoType` also needs to be
copyable. This limits the design space. We could intern `TodoType`, but
I discarded this option, as it would require us to have access to the
salsa DB everywhere we want to use `Type::Todo`. And it would have made
the macro invocations less ergonomic (requiring us to pass `db`).

So for now, the meta information is simply a `&'static str` / `u32` for
the file/line variant, or a `&'static str` for the custom message.
Anything involving a chain/backtrace of several `@Todo`s or similar is
therefore currently not implemented. Also because we currently don't see
any direct use cases for this, and because all of this will eventually
go away.

Note that the size of `Type` increases from 16 to 24 bytes, but only in
debug mode.

## Test Plan

- Observed the changes in Markdown tests.
- Added custom messages for all `Type::Todo`s that were revealed in the
tests
- Ran red knot in release and debug mode on the following Python file:
  ```py
  def f(x: int) -> int:
      reveal_type(x)
  ```
Prints `@Todo` in release mode and `@Todo(function parameter type)` in
debug mode.
2024-11-21 09:59:47 +01:00
Alex Waygood
df45a0e3f9
[red-knot] Add MRO resolution for classes (#14027) 2024-11-04 13:31:38 +00:00
Carl Meyer
b8acadd6a2
[red-knot] have mdformat wrap mdtest files to 100 columns (#14020)
This makes it easier to read and edit (and review changes to) these
files as source, even though it doesn't affect the rendering.
2024-10-31 21:00:51 +00:00
Alex Waygood
3eb454699a
[red-knot] Format mdtest Python snippets more concisely (#13905) 2024-10-24 11:09:31 +00:00
Shaygan Hooshyari
0f0fff4d5a
[red-knot] Implement more types in binary and unary expressions (#13803)
Implemented some points from
https://github.com/astral-sh/ruff/issues/12701

- Handle Unknown and Any in Unary operation
- Handle Boolean in binary operations
- Handle instances in unary operation
- Consider division by False to be division by zero

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-10-20 01:57:21 +00:00
Alex Waygood
55bccf6680
[red-knot] Fix edge case for binary-expression inference where the lhs and rhs are the exact same type (#13823)
## Summary

This fixes an edge case that @carljm and I missed when implementing
https://github.com/astral-sh/ruff/pull/13800. Namely, if the left-hand
operand is the _exact same type_ as the right-hand operand, the
reflected dunder on the right-hand operand is never tried:

```pycon
>>> class Foo:
...     def __radd__(self, other):
...         return 42
...         
>>> Foo() + Foo()
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    Foo() + Foo()
    ~~~~~~^~~~~~~
TypeError: unsupported operand type(s) for +: 'Foo' and 'Foo'
```

This edge case _is_ covered in Brett's blog at
https://snarky.ca/unravelling-binary-arithmetic-operations-in-python/,
but I missed it amongst all the other subtleties of this algorithm. The
motivations and history behind it were discussed in
https://mail.python.org/archives/list/python-dev@python.org/thread/7NZUCODEAPQFMRFXYRMGJXDSIS3WJYIV/

## Test Plan

I added an mdtest for this cornercase.
2024-10-19 11:09:54 -07:00
Carl Meyer
f4b5e70fae
[red-knot] binary arithmetic on instances (#13800)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-10-19 15:22:54 +00:00
Alex Waygood
36cb1199cc
[red-knot] Autoformat mdtest Python snippets using blacken-docs (#13809) 2024-10-19 15:57:06 +01:00
David Peter
c2f7c39987
[red-knot] mdtest suite: formatting and cleanup (#13806)
Minor cleanup and consistent formatting of the Markdown-based tests.

- Removed lots of unnecessary `a`, `b`, `c`, … variables.
- Moved test assertions (`# revealed:` comments) closer to the tested
object.
- Always separate `# revealed` and `# error` comments from the code by
two spaces, according to the discussion
[here](https://github.com/astral-sh/ruff/pull/13746/files#r1799385758).
This trades readability for consistency in some cases.
- Fixed some headings
2024-10-18 11:07:53 +02:00
Carl Meyer
e2a30b71f4
[red-knot] revert change to emit fewer division by zero errors (#13801)
This reverts https://github.com/astral-sh/ruff/pull/13799, and restores
the previous behavior, which I think was the most pragmatic and useful
version of the divide-by-zero error, if we will emit it at all.

In general, a type checker _does_ emit diagnostics when it can detect
something that will definitely be a problem for some inhabitants of a
type, but not others. For example, `x.foo` if `x` is typed as `object`
is a type error, even though some inhabitants of the type `object` will
have a `foo` attribute! The correct fix is to make your type annotations
more precise, so that `x` is assigned a type which definitely has the
`foo` attribute.

If we will emit it divide-by-zero errors, it should follow the same
logic. Dividing an inhabitant of the type `int` by zero may not emit an
error, if the inhabitant is an instance of a subclass of `builtins.int`
that overrides division. But it may emit an error (more likely it will).
If you don't want the diagnostic, you can clarify your type annotations
to require an instance of your safe subclass.

Because the Python type system doesn't have the ability to explicitly
reflect the fact that divide-by-zero is an error in type annotations
(e.g. for `int.__truediv__`), or conversely to declare a type as safe
from divide-by-zero, or include a "nonzero integer" type which it is
always safe to divide by, the analogy doesn't fully apply. You can't
explicitly mark your subclass of `int` as safe from divide-by-zero, we
just semi-arbitrarily choose to silence the diagnostic for subclasses,
to avoid false positives.

Also, if we fully followed the above logic, we'd have to error on every
`int / int` because the RHS `int` might be zero! But this would likely
cause too many false positives, because of the lack of a "nonzero
integer" type.

So this is just a pragmatic choice to emit the diagnostic when it is
very likely to be an error. It's unclear how useful this diagnostic is
in practice, but this version of it is at least very unlikely to cause
harm.
2024-10-17 20:17:22 +00:00
Carl Meyer
5c537b6dbb
[red-knot] don't emit divide-by-zero error if we can't be sure (#13799)
If the LHS is just `int` or `float` type, that type includes custom
subclasses which can arbitrarily override division behavior, so we
shouldn't emit a divide-by-zero error in those cases.

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-10-17 17:11:07 +00:00
Alex
d77480768d
[red-knot] Port type inference tests to new test framework (#13719)
## Summary

Porting infer tests to new markdown tests framework.

Link to the corresponding issue: #13696

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2024-10-15 11:23:46 -07:00