sympy / sympy

A computer algebra system written in pure Python
https://sympy.org/
Other
13k stars 4.44k forks source link

Expression of type "Expr | int" cannot be assigned to declared type "Expr" #23323

Open sdykae opened 2 years ago

sdykae commented 2 years ago

I known this is not a problem but for type safe writting, is there a way to craft an Expr that handles the input types and make mypy no mistake? image

oscarbenjamin commented 2 years ago

I think the problem is that Expr.__pow__ is actually not type consistent because it sometimes returns unsympified ints. This seems to fix it:

diff --git a/sympy/core/expr.py b/sympy/core/expr.py
index 9fc041f..9a0c299 100644
--- a/sympy/core/expr.py
+++ b/sympy/core/expr.py
@@ -229,10 +229,10 @@ def __pow__(self, other, mod=None):
         try:
             _self, other, mod = as_int(self), as_int(other), as_int(mod)
             if other >= 0:
-                return pow(_self, other, mod)
+                return _sympify(pow(_self, other, mod))
             else:
                 from .numbers import mod_inverse
-                return mod_inverse(pow(_self, -other, mod), mod)
+                return _sympify(mod_inverse(pow(_self, -other, mod), mod))
         except ValueError:
             power = self._pow(other)
             try:

Looks like mod_inverse is also inconsistent.

nishant-sg commented 2 years ago

Hello, I would like to contribute to this issue, can you guide me on what needs to be done?

fauzank339 commented 2 years ago

Hello. I want to look into this issue can anyone guide me.

eagleoflqj commented 2 years ago

Now the error is gone, but deduced type becomes Unknown:

from typing_extensions import reveal_type
from sympy import *

x = Symbol('x')
reveal_type(x**2)
reveal_type(x**2-16)
$ pyright test.py
...
  test.py:5:13 - information: Type of "x ** 2" is "Expr"
  test.py:6:13 - information: Type of "x ** 2 - 16" is "Unknown"

Some more type hints should be added so that you don't need to explicitly say fb is Expr.

eagleoflqj commented 2 years ago

No, adding type hints doesn't help due to https://github.com/sympy/sympy/blob/a6e74d2b8b3b64e8cdbf4c2f21835e234eb92d65/sympy/core/expr.py#L204 With the decorator, __sub__ of Expr is a _SympifyWrapper object instead of a method. It's converted back to a method at https://github.com/sympy/sympy/blob/a6e74d2b8b3b64e8cdbf4c2f21835e234eb92d65/sympy/core/decorators.py#L178-L181 It's definitely not understandable by pyright.

u7122029 commented 2 years ago

Now the error is gone, but deduced type becomes Unknown:

from typing_extensions import reveal_type
from sympy import *

x = Symbol('x')
reveal_type(x**2)
reveal_type(x**2-16)
$ pyright test.py
...
  test.py:5:13 - information: Type of "x ** 2" is "Expr"
  test.py:6:13 - information: Type of "x ** 2 - 16" is "Unknown"

Some more type hints should be added so that you don't need to explicitly say fb is Expr.

Hey, I just ran your shell test

$ python
...
>>> from typing_extensions import reveal_type
>>> from sympy import *
>>> x = Symbol('x')
>>> reveal_type(x**2)
Runtime type is 'Pow'
x**2
>>> reveal_type(x**2-16)
Runtime type is 'Add'
x**2 - 16

It seems that the expression is being read correctly? Please note that I am a new contributor and I'm not sure how much has changed about sympy since the last comment in this issue. Perhaps I'm wrong to say that we could close this issue.

eagleoflqj commented 2 years ago

No. Please use pyright to test this issue.