Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Out of memory error when passing a generic function into a generic callable protocol #7250

Closed
LeeeeT opened this issue Feb 12, 2024 · 5 comments
Labels
addressed in next version Issue is fixed and will appear in next published version bug Something isn't working

Comments

@LeeeeT
Copy link

LeeeeT commented Feb 12, 2024

For the following code, pyright is doing something weird:

from typing import Protocol

class P(Protocol):
    def __call__[T](self, a: T) -> T:
        ...

def f[T](a: T) -> T:
    return a

def g(p: P) -> P:
    return p(f)

The error message is kinda funny:

file.py:11:12 - error: Expression of type "(a: (a: (a: (a: (a: (a: (a: T@f) -> T@f) -> ((a: T@f) -> T@f)) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))))) -> ((a: ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))))) -> ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))))" cannot be assigned to return type "P"
  Type "(a: (a: (a: (a: (a: (a: (a: T@f) -> T@f) -> ((a: T@f) -> T@f)) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))))) -> ((a: ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))))) -> ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))))" cannot be assigned to type "(a: T@__call__) -> T@__call__"
    Parameter 1: type "T@__call__" cannot be assigned to type "(a: (a: (a: (a: (a: (a: T@f) -> T@f) -> ((a: T@f) -> T@f)) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))))"
      Type "T@__call__" cannot be assigned to type "(a: (a: (a: (a: (a: (a: T@f) -> T@f) -> ((a: T@f) -> T@f)) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))))"
    Function return type "(a: (a: (a: (a: (a: (a: T@f) -> T@f) -> ((a: T@f) -> T@f)) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))))" is incompatible with type "T@__call__"
      Type "(a: (a: (a: (a: (a: (a: T@f) -> T@f) -> ((a: T@f) -> T@f)) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))))) -> ((a: ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))) -> ((a: ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f))) -> ((a: ((a: T@f) -> T@f)) -> ((a: T@f) -> T@f)))))" cannot be assigned to type "T@__call__"

If you add a second argument to P and f like this...

from typing import Protocol

class P(Protocol):
    def __call__[T](self, a: T, b: T) -> T:
        ...

def f[T](a: T, b: T) -> T:
    return a

def g(p: P) -> P:
    return p(f, f)

...then pyright runs out of memory:

<--- Last few GCs --->

[2875:0xb400007235ad6540]    63230 ms: Scavenge 1016.0 (1036.5) -> 1015.0 (1037.2) MB, 3.67 / 0.00 ms  (average mu = 0.111, current mu = 0.076) allocation failure;
[2875:0xb400007235ad6540]    63235 ms: Scavenge 1016.4 (1037.2) -> 1015.4 (1037.5) MB, 3.21 / 0.00 ms  (average mu = 0.111, current mu = 0.076) allocation failure;
[2875:0xb400007235ad6540]    63240 ms: Scavenge 1016.9 (1037.5) -> 1015.9 (1042.0) MB, 2.91 / 0.00 ms  (average mu = 0.111, current mu = 0.076) allocation failure;

<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
@LeeeeT LeeeeT added the bug Something isn't working label Feb 12, 2024
@LeeeeT LeeeeT changed the title Out of memory error when passing a generic function into generic function which is a member of a Protocol Out of memory error when passing a generic function into a generic function which is a member of a Protocol Feb 12, 2024
@LeeeeT LeeeeT changed the title Out of memory error when passing a generic function into a generic function which is a member of a Protocol Out of memory error when passing a generic function into a generic callable protocol Feb 12, 2024
@LeeeeT
Copy link
Author

LeeeeT commented Apr 1, 2024

I've found a similar code sample that causes pyright to enter an infinite loop, but it doesn't run out of memory. I suppose the nature of the bugs for all these examples is the same. This can also be related to #7141.

def id[T](v: T) -> T:
    return v

id((id, id))

@minmax
Copy link

minmax commented Apr 26, 2024

I'm not sure if this is related to the topic, but I also managed to get OOM from pyright 1.1.360.

"JavaScript heap out of memory":

from datetime import datetime

from datetype import NaiveDateTime
from django.db.models import DateTimeField

def g() -> NaiveDateTime:
    return datetime.now()

DateTimeField(default=g)

datetype.NaiveDateTime is a Protocol from https://github.com/glyph/DateType

@erictraut
Copy link
Collaborator

@minmax, that's a different issue. Could you please file a separate bug so it's tracked accordingly? Thanks!

@minmax
Copy link

minmax commented Apr 27, 2024

@minmax, that's a different issue. Could you please file a separate bug so it's tracked accordingly? Thanks!

ok, add separate bug #7786

@erictraut erictraut added the addressed in next version Issue is fixed and will appear in next published version label May 21, 2024
@erictraut
Copy link
Collaborator

This is addressed in pyright 1.1.364.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addressed in next version Issue is fixed and will appear in next published version bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants