Special-case value-expression inference of special form subscriptions (#16877)

## Summary

Currently for something like `X = typing.Tuple[str, str]`, we infer the
value of `X` as `object`. That's because `Tuple` (like many of the
symbols in the typing module) is annotated as a `_SpecialForm` instance
in typeshed's stubs:


23382f5f8c/crates/red_knot_vendored/vendor/typeshed/stdlib/typing.pyi (L215)

and we don't understand implicit type aliases yet, and the stub for
`_SpecialForm.__getitem__` says it always returns `object`:


23382f5f8c/crates/red_knot_vendored/vendor/typeshed/stdlib/typing.pyi (L198-L200)

We have existing false positives in our test suite due to this:


23382f5f8c/crates/red_knot_python_semantic/resources/mdtest/annotations/annotated.md (L76-L78)

and it's causing _many_ new false positives in #16872, which tries to
make our annotation-expression parsing stricter in some ways.

This PR therefore adds some small special casing for `KnownInstanceType`
variants that fallback to `_SpecialForm`, so that these false positives
can be avoided.

## Test Plan

Existing mdtest altered.

Cc. @MatthewMckee4
This commit is contained in:
Alex Waygood 2025-03-20 21:46:02 +00:00 committed by GitHub
parent 42cbce538b
commit 296d67a496
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 10 additions and 3 deletions

View file

@ -73,12 +73,10 @@ Inheriting from `Annotated[T, ...]` is equivalent to inheriting from `T` itself.
```py
from typing_extensions import Annotated
# TODO: False positive
# error: [invalid-base]
class C(Annotated[int, "foo"]): ...
# TODO: Should be `tuple[Literal[C], Literal[int], Literal[object]]`
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Unknown, Literal[object]]
reveal_type(C.__mro__) # revealed: tuple[Literal[C], @Todo(Inference of subscript on special form), Literal[object]]
```
### Not parameterized

View file

@ -851,6 +851,10 @@ impl<'db> KnownClass {
matches!(self, Self::Bool)
}
pub(crate) const fn is_special_form(self) -> bool {
matches!(self, Self::SpecialForm)
}
/// Determine whether instances of this class are always truthy, always falsy,
/// or have an ambiguous truthiness.
pub(crate) const fn bool(self) -> Truthiness {

View file

@ -5631,6 +5631,11 @@ impl<'db> TypeInferenceBuilder<'db> {
(Type::KnownInstance(KnownInstanceType::Protocol), _) => {
Type::Dynamic(DynamicType::TodoProtocol)
}
(Type::KnownInstance(known_instance), _)
if known_instance.class().is_special_form() =>
{
todo_type!("Inference of subscript on special form")
}
(value_ty, slice_ty) => {
// If the class defines `__getitem__`, return its return type.
//