Skip to content

Wrong inference for abs/__abs__ or function that calls a method on a generic type.Β #19609

@oscarbenjamin

Description

@oscarbenjamin

This was discussed in the typing forums.

Here mypy (latest version 1.17.1) infers the type of abs(value) incorrectly:

from typing import Self

class Real:
    def __abs__(self) -> Self:
        return self

def my_abs[T: Real](value: T):
    reveal_type(abs(value))      # Real
    reveal_type(value.__abs__()) # T

That is:

$ mypy z.py 
z.py:8: note: Revealed type is "z.Real"
z.py:9: note: Revealed type is "T`-1"
Success: no issues found in 1 source file

Since abs just calls __abs__ they return the same type which should be inferred as T in both cases.

I show the simpler example above with a concrete Real type but what I actually want to do is have a Protocol for abs:

from typing import Self, Protocol

class HasAbs(Protocol):
    def __abs__(self) -> Self:
        return self

def my_abs[T: HasAbs](value: T) -> T:
    return abs(value)

However mypy incorrectly rejects this because it infers the type of abs(value) incorrectly:

$ mypy z.py 
z.py:8: error: Incompatible return value type (got "HasAbs", expected "T")  [return-value]
Found 1 error in 1 file (checked 1 source file)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions