Turned out, previously such recursive protocol declarations, when
one of its methods returns the same protocol and the corresponding
implementation method returns `typing.Self` where handled thanks
to considering PySelfType as unknown (see `PyTypeCheker.isUnknown()`),
so a raw, not substituted, `Self` matched any protocol.
We didn't get notable false negatives due to that because normally
PySelfType is substituted with the corresponding receiver type
before matching, and protocols are one of a few exceptions,
where we match against raw Self in method signatures.
Matching such a protocol with an implementation returning not
`typing.Self`, but the same class, always caused recursion guard hits.
Now that PySelfType is considered equivalent to its scope class type,
implementations using Self also trigger it. I've added explicit tests
on that for further investigation.
GitOrigin-RevId: 2cc0432438f0049db005ad50c563f20cc845e44e
Merge-request: IJ-MR-186102
Merged-by: Nikita Ashihmin <Nikita.Ashihmin@jetbrains.com>
Key features:
- Added Wrapper PSI elements that are not sent to Pyrefly for type calculation because they simply use the type of another element.
- Added more instant type annotations for types that do not require context for type calculation.
- Supported Pyrefly LSP type inference. To use it, the following fork is required: https://github.com/nashikhmin/pyrefly
- Added a separate context because built-in constraints are not applicable to Pyrefly.
- The first ten types are calculated one-by-one to ensure quick responses for completion; however, subsequent types are calculated in batches for better time efficiency.
GitOrigin-RevId: 890c86d623905493063823b4bc03b6153069e0c1
- Added PyPatternInspection class with logic to highlight and fix issues in pattern matching
- Modified PyAstAsPattern.getTarget() to return nullable value
- Added quick fix for PyAsPattern to simplify patterns
- Added quick fix for PyClass to add `__match_args__` attribute based on `__init__` signature
- Added PyRemoveElementFix quick fix to clean invalid list elements
- Added validation in PyPatternInspection to detect excessive positional patterns
- Added conflict detection between positional and named patterns in PyPatternInspection
GitOrigin-RevId: 64a1693aae2d243b83c46883a5d8476e727562a8
When we have a protocol hierarchy, such as the following
```python
class P[T](Protocol):
def method(self, x: T) -> T:
pass
class P2[T](P[T], Protocol):
pass
def expects_generic(x: P2[str]): ...
```
substitutions extracted from the expected type `P2[str]` of `x` are:
```
T@P2 -> str
T@P -> T@P2
```
Doing `expectedSubstitutions.withOnlySolvedSubstitutions(context)) then
throws away `T@P -> T@P2` mapping, so we lose that `T@P` is supposed to be str.
It means that during matching of `P.method` we match its unbound T@P
with any actual type, causing false positives.
On the other hand, if `expects_generic` was supposed to bind its own parameter,
e.g. as if in
```python
def expects_generic[T](x: P2[T]) -> T: ...
```
we cannot restore the actual type of `T@expects_generic` in the
```java
if (expected instanceof PyCollectionType) ...
```
branch at the end, because we try to match
`P2[T@expects_generic]` (expected type) with `P2[T@P2]` with substitution `T@P -> str`
(for example). Again, because the mapping `T@P -> T@P2` is lost, we end up
only binding `T@expects_generic -> T@P2`.
Now we substitute everything into the "raw" protocol member type before
matching it with the implementation, so we map `T@expects_generic` right away
when matching `P.method` with implementation,
and then we only need to insert this type into the expected
`P2[T@expects_generic]`.
GitOrigin-RevId: 88c91add1cca181db14f3276f944a84dffcd6517
This prevents the caches from blowing up in size when analyzing a lot of files in a row
The most obvious example is running `Analyze code` on the whole project. Previously, all PSI elements from all files would pollute the cache, potentially consuming multiple Gb of memory. See PyDjangoSourcesPerformanceTest as an example. It used to require 16 Gb of heap, and it would still sometimes fail with OOM. Now, it runs smoothly with 2Gb of heap
GitOrigin-RevId: f9854f8abdd7086414df8f610b0f2d611ca0d455
Because the callable type for dataclass callees is provided, the special logic for PySelfType
in `PyCallExpressionHelper.getExplicitResolveResults` didn't apply to dataclasses, so
invoking their constructor as `cls()` in class methods returned a concrete class instance,
not Self. I changed `PyDataclassTypeProvider.getDataclassTypeForClass` to accept a PyType,
instead of a raw PyClass, so PyClassTypeImpl and PySelfType (which is a PyClassType)
should be processed uniformly.
GitOrigin-RevId: 3ef0be3bfaec16283b7b74914e3e2dbee7c683cd
Ideally, it should be an intersection of these types, but UnsafeUnion
at least allows avoiding false positives.
GitOrigin-RevId: 154849f814921f3a13534b72a1d10d309069a23e
- introduces PyExpectedTypeJudgement as a single entry to compute expected types
- changes a few clients to use PyExpectedTypeJudgement
GitOrigin-RevId: 27734b99b37a364b540f8af985908b282c50afd7