You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
False positive on _ (underscore) as variable name with disallow-any-expr #15253
main.py:16: error: Expression type contains "Any" (has type "Tuple[Any, float]") [misc]
main.py:16: error: Expression has type "Any" [misc]
Found 2 errors in 1 file (checked 1 source file)
Your Environment
(environment of the playground)
Mypy version used: 1.3.0
Mypy command-line flags: --disallow-any-expr
Python version used: 3.8 (same for other versions)
The code provided contains two errors when calling the wrapper function. I will explain each error and provide a corrected version of the code.
Error: Missing argument in wrapper function call
The line _, c = wrapper(func) is missing the argument fn in the wrapper function call. The wrapper function expects a callable function as an argument, but it is not provided in this case.
Correction:
To fix this error, you need to pass the func function as an argument to the wrapper function. Here's the corrected code:
Error: Incorrect number of values to unpack
The line b, c = wrapper(func) tries to unpack two values from the return value of wrapper, but the wrapper function actually returns a single value wrapped in a tuple.
Correction:
To fix this error, you can modify the wrapper function to return a tuple containing the result and a default value for the float. Alternatively, you can modify the line to only assign the first value of the tuple. Here's the corrected code using the second approach:
For what it's worth, widening the special case that allows wrapper2 to work does not work, unfortunately. I tried that and a bunch of type errors across mypy's codebase popped up :(
Do you know of how it could maybe generalize? Or if this is just some issue that takes more effort than warranted. I see you added a comment right above about some sort of solution, but I'm not exactly sure of what this entails or whether maybe there's a better way nowadays:
# * We need to update all the inference "infrastructure", so that all
# variables in an expression are inferred at the same time.
# (And this is hard, also we need to be careful with lambdas that require
# two passes.)
Specifically, mypy is seeing a ret_type of T'1 for wrapper2, and a ret_type of tuple[T'1, float] for wrapper. erased_ctx is Any for both. This means wrapper2 lucks into having a special case meaning it doesn't get modified, but for wrapper, T'1 gets constrained to Any and that gets inferred through.
That special-casing is really fragile, I wouldn't modify it (either way) unless really needed.
I think the problem here may be that kind of Any gets lost somehow. We should never count AnyType(TypeOfAny.special_form) as a real Any (and we should already do this, see HasAnyType visitor in checkexpr.py). I guess what happens is that during inference we get a new Any, and it may be the new Any gets e.g. kind TypeOfAny.from_another_any. So that visitor should be fixed to also exclude TypeOfAny.from_another_any, where source_any.type_of_any == TypeOfAny.special_form (no need to recurse btw since constructor already handles this).
Btw I think is_special_form_any() in stats.py may also need updating, but that is more tricky, because for stats we sometimes do count special form Any as a "real" Any.
Activity
AVUKU-PRAGATHESWARI commentedon May 16, 2023
The code provided contains two errors when calling the wrapper function. I will explain each error and provide a corrected version of the code.
Error: Missing argument in wrapper function call
The line _, c = wrapper(func) is missing the argument fn in the wrapper function call. The wrapper function expects a callable function as an argument, but it is not provided in this case.
Correction:
To fix this error, you need to pass the func function as an argument to the wrapper function. Here's the corrected code:
Error: Incorrect number of values to unpack
The line b, c = wrapper(func) tries to unpack two values from the return value of wrapper, but the wrapper function actually returns a single value wrapped in a tuple.
Correction:
To fix this error, you can modify the wrapper function to return a tuple containing the result and a default value for the float. Alternatively, you can modify the line to only assign the first value of the tuple. Here's the corrected code using the second approach:
`from typing import Callable, Tuple, TypeVar
T = TypeVar("T")
def wrapper(fn: Callable[[], T]) -> Tuple[T, float]:
return fn(), 1.0
def wrapper2(fn: Callable[[], T]) -> T:
return fn()
def func() -> int:
x = 1
return x
def a() -> None:
_, c = wrapper(func)
b = wrapper(func)
_ = wrapper2(func)
_, c = #`wrapper(func)``
AVUKU-PRAGATHESWARI commentedon May 16, 2023
from typing import Callable, Tuple, TypeVar
T = TypeVar("T")
def wrapper(fn: Callable[[], T]) -> Tuple[T, float]:
return fn(), 1.0
def wrapper2(fn: Callable[[], T]) -> T:
return fn()
def func() -> int:
x = 1
return x
def a() -> None:
_, c = wrapper(func)
b = wrapper(func)
_ = wrapper2(func)
_, c = wrapper(func)
I hope this code will rectify the error..
lkct commentedon May 16, 2023
@AVUKU-PRAGATHESWARI Sorry, I don't think your answer is correct.
(And, no offence, but I doubt if I'm talking to human.)
AVUKU-PRAGATHESWARI commentedon May 18, 2023
I am a human😊...But its fine
A5rocks commentedon May 21, 2023
Here's a more minimal reproduction!:
It only shows a single error, though. ... Oh, it's cause this:
mypy/mypy/semanal.py
Lines 3737 to 3741 in 2ede35f
Uhhhhhhhhhhh, I'll think about this.
A5rocks commentedon May 21, 2023
For what it's worth, widening the special case that allows
wrapper2to work does not work, unfortunately. I tried that and a bunch of type errors across mypy's codebase popped up :(A5rocks commentedon May 21, 2023
@ilevkivskyi you initially added this special case in 626ff689e6df171e1aec438b905efdf999bdc09e
Do you know of how it could maybe generalize? Or if this is just some issue that takes more effort than warranted. I see you added a comment right above about some sort of solution, but I'm not exactly sure of what this entails or whether maybe there's a better way nowadays:
Specifically, mypy is seeing a
ret_typeofT'1forwrapper2, and aret_typeoftuple[T'1, float]forwrapper.erased_ctxisAnyfor both. This meanswrapper2lucks into having a special case meaning it doesn't get modified, but forwrapper,T'1gets constrained toAnyand that gets inferred through.A5rocks commentedon Jun 15, 2023
@ilevkivskyi again in case you haven't seen this yet
I found another case of this in some code a friend wrote
ilevkivskyi commentedon Jun 16, 2023
That special-casing is really fragile, I wouldn't modify it (either way) unless really needed.
I think the problem here may be that kind of
Anygets lost somehow. We should never countAnyType(TypeOfAny.special_form)as a realAny(and we should already do this, seeHasAnyTypevisitor incheckexpr.py). I guess what happens is that during inference we get a newAny, and it may be the newAnygets e.g. kindTypeOfAny.from_another_any. So that visitor should be fixed to also excludeTypeOfAny.from_another_any, wheresource_any.type_of_any == TypeOfAny.special_form(no need to recurse btw since constructor already handles this).Btw I think
is_special_form_any()instats.pymay also need updating, but that is more tricky, because for stats we sometimes do count special formAnyas a "real"Any.DetachHead commentedon Jun 20, 2023
here's a more minimal example:
ilevkivskyi commentedon Jun 22, 2023
Hm, unfortunately my idea uncovered a big underlying issue, see #15497 (comment)