[Bug][CLI]: Wrong inference (incorrect narrowing?)
Describe the Bug
Given:
def shown(x):
whole = float(x)
return x - whole
I expect x to be Any so x - whole might be float, or might be Any. But instead I get errors on x - whole. Seems we have decided that x must be one of the arguments to float, or perhaps all of them? Not really sure.
Codebase
https://pyrefly.org/sandbox/?code=CYUwZgBAzgFg9gdwHYAoAeBKAXAKAviBeAGxAgF4Ixi4BDAF3QzwICcR6BXVpCNCALSESIHEA
Other Attempts
No response
Oh I think I know what's happening here - I bet we're checking for __sub__ on x, not finding it, and falling back to float.__rsub__. But we need to check for Any somewhere in there.
EDIT: Actually, I'm confused about where all those argument types are coming from...
I was totally wrong about this one XD
When I print out the arguments that binop_infer is getting, x is a Var and whole is a float. Expanding that Var gives me Buffer | SupportsFloat | SupportsIndex | str, which matches ConvertibleToFloat in float.__new__: https://github.com/python/typeshed/blob/4265ee7c72f476e7156949e55784fd82b40e6953/stdlib/builtins.pyi#L337. Looks like what's happening is:
def shown(x): # type of x is a Var
whole = float(x) # type of x is solved to ConvertibleToFloat because of the call to float.__new__
return x - whole # we generate an error for each type in the ConvertibleToFloat union that can't be subtracted from a float
Why is type of x is a Var the conclusion? I thought that argument types should be inferred to be Any(Implicit) not Var?
Oops, yeah, I was wrong about where the Var is coming from. It's actually from a promote_recursive call (https://github.com/facebook/pyrefly/blob/2e7bef2b198a0ac34fa713d8139ff707ab97ee51/pyrefly/lib/alt/traits.rs#L123). Interestingly, the return statement is needed to trigger the bug; https://pyrefly.org/sandbox/?code=CYUwZgBAzgFg9gdwHYAoAeBKAXAKAviBeAGxAgF4Ixi4BDAF3QzwIE8KI0IBaQkkIA works just fine.
I think I might be seeing the same issue in abs().
In a Vector class with attributes of x,y and z that are type hinted as Union[int,float]...
class BaseVector(NamedTuple):
"""
Base class for vector-like objects.
This class is used to define the basic structure of a vector, including
its x, y, and z components. It is intended to be subclassed by more
specific vector classes.
"""
x: Union[int, float] = 0
y: Union[int, float] = 0
z: Union[int, float] = 0
I am declaring the abs dunder method as:
def __abs__(self) -> Self:
return Vector(abs(self.x), abs(self.y), abs(self.z))
In VS Code, using extension version 0.20.0 and the Pyrefly package version 0.20.0, I get the error.
Argument 'float | int' is not assignable to parameter x the with type 'SupportsAbs[int]' in function 'abs' Pyrely(bad-argument-type)
Expected behaviour is that Union[int,float] should not be flagged as a bad argument for the abs() function which appears to accept int, float, complex and anything that implements its own __abs__ method.
Does this look like the same thing or should I log a new bug?
Many thanks.
@DannyGoodall I don't think your bug is the same issue - I suspect it was caused by overload handling, and as far as I can tell it is now fixed, see this (slightly modified) version of your example.
The original bug also seems to be fixed - I suspect it may have had to do with union attribute lookups, since - desugars to a dunder call.