Skip to content

abstractmethod + generic method seems to disturb inference results #7863

@beezee

Description

@beezee

I believe this would qualify as a bug.

When a method takes generic input types that are also present in the return type, and that method is defined as abstract, the revealed type of the method appears correct, but the inferred type of the returned value is not consistent with the inferred method type. This is resolved when the method is not declared abstract.

I have a very broad use case for this code, but I've minimized for the example here. I hope this is clear and please let me know if there's anything else I can add or help with.

from abc import ABC, abstractmethod
from typing import Generic, TypeVar

A = TypeVar('A')
B = TypeVar('B')

class TwoTypes(Generic[A, B]): pass

class MakeTwoSurprise(ABC, Generic[A]):

  @abstractmethod
  def __call__(self, a: B) -> TwoTypes[A, B]: pass

class MakeTwoExpected(Generic[A]):

  def __call__(self, a: B) -> TwoTypes[A, B]: pass


class Test():
  
  def make_two(self, 
                mts: MakeTwoSurprise[A], 
                mte: MakeTwoExpected[A]) -> None:
    reveal_type(mts.__call__) # Revealed type is 'def [B] (a: B`-1) -> repro.TwoTypes[A`-1, B`-1]'
    reveal_type(mts(2)) # Revealed type is 'repro.TwoTypes[builtins.int*, builtins.int*]'
    reveal_type(mte.__call__) # Revealed type is 'def [B] (a: B`2) -> repro.TwoTypes[A`-1, B`2]'
    reveal_type(mte(2)) # Revealed type is 'repro.TwoTypes[A`-1, builtins.int*]'

I'd expect both of these implementations to typecheck identically, but more importantly you can see reveal_type(mts(2)) has inferred int for both type arguments in TwoTypes, even though the first argument, while still unknown to the implementation of make_two, would have previously been determined by a caller of this method, based on the instance of MakeTwoSurprise that they had passed.

Any and all feedback/assistance is greatly appreciated.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy