Skip to content

Remove TypeType exception for abstract instantiation #18094

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
@@ -1668,21 +1668,14 @@ def check_callable_call(
# An Enum() call that failed SemanticAnalyzerPass2.check_enum_call().
return callee.ret_type, callee

if (
callee.is_type_obj()
and callee.type_object().is_protocol
# Exception for Type[...]
and not callee.from_type_type
):
if callee.is_type_obj() and callee.type_object().is_protocol:
self.chk.fail(
message_registry.CANNOT_INSTANTIATE_PROTOCOL.format(callee.type_object().name),
context,
)
elif (
callee.is_type_obj()
and callee.type_object().is_abstract
# Exception for Type[...]
and not callee.from_type_type
and not callee.type_object().fallback_to_any
):
type = callee.type_object()
20 changes: 8 additions & 12 deletions test-data/unit/check-abstract.test
Original file line number Diff line number Diff line change
@@ -187,7 +187,7 @@ class C(B):
pass

def f(cls: Type[A]) -> A:
return cls() # OK
return cls() # E: Cannot instantiate abstract class "A" with abstract attribute "m"
def g() -> A:
return A() # E: Cannot instantiate abstract class "A" with abstract attribute "m"

@@ -196,7 +196,6 @@ f(B) # E: Only concrete class can be given where "Type[A]" is expected
f(C) # OK
x: Type[B]
f(x) # OK
[out]

[case testAbstractTypeInADict]
from typing import Dict, Type
@@ -229,15 +228,14 @@ class C(B):
pass

def f(cls: Type[A]) -> A:
return cls() # OK
return cls() # E: Cannot instantiate abstract class "A" with abstract attribute "m"

Alias = A
GoodAlias = C
Alias() # E: Cannot instantiate abstract class "A" with abstract attribute "m"
GoodAlias()
f(Alias) # E: Only concrete class can be given where "Type[A]" is expected
f(GoodAlias)
[out]

[case testInstantiationAbstractsInTypeForVariables]
# flags: --no-strict-optional
@@ -253,7 +251,7 @@ class C(B):
pass

var: Type[A]
var()
var() # E: Cannot instantiate abstract class "A" with abstract attribute "m"
if int():
var = A # E: Can only assign concrete classes to a variable of type "Type[A]"
if int():
@@ -262,7 +260,7 @@ if int():
var = C # OK

var_old = None # type: Type[A] # Old syntax for variable annotations
var_old()
var_old() # E: Cannot instantiate abstract class "A" with abstract attribute "m"
if int():
var_old = A # E: Can only assign concrete classes to a variable of type "Type[A]"
if int():
@@ -278,7 +276,7 @@ class D(A):
def __new__(cls, a=None) -> "D": ...
if int():
var = D # E: Can only assign concrete classes to a variable of type "Type[A]"
[out]


[case testInstantiationAbstractsInTypeForClassMethods]
from typing import Type
@@ -291,13 +289,12 @@ class Logger:
class C:
@classmethod
def action(cls) -> None:
cls() #OK for classmethods
cls() # E: Cannot instantiate abstract class "C" with abstract attribute "m"
Logger.log(cls) #OK for classmethods
@abstractmethod
def m(self) -> None:
pass
[builtins fixtures/classmethod.pyi]
[out]

[case testInstantiatingClassWithInheritedAbstractMethodAndSuppression]
from abc import abstractmethod, ABCMeta
@@ -324,7 +321,6 @@ class A(metaclass=ABCMeta):
@abstractmethod
def j(self): pass
a = A() # E: Cannot instantiate abstract class "A" with abstract attributes "a", "b", ... and "j" (7 methods suppressed)
[out]


-- Implementing abstract methods
@@ -1085,9 +1081,9 @@ my_abstract_types = {
reveal_type(my_concrete_types) # N: Revealed type is "builtins.dict[builtins.str, def () -> __main__.MyAbstractType]"
reveal_type(my_abstract_types) # N: Revealed type is "builtins.dict[builtins.str, def () -> __main__.MyAbstractType]"

a = my_concrete_types['A']()
a = my_concrete_types['A']() # E: Cannot instantiate abstract class "MyAbstractType" with abstract attribute "do"
a.do()
b = my_concrete_types['B']()
b = my_concrete_types['B']() # E: Cannot instantiate abstract class "MyAbstractType" with abstract attribute "do"
b.do()

c = my_abstract_types['A']() # E: Cannot instantiate abstract class "MyAbstractType" with abstract attribute "do"
3 changes: 2 additions & 1 deletion test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
@@ -1526,7 +1526,8 @@ import typing
class C:
@classmethod
def foo(cls) -> None:
cls().bar()
c = cls() # E: Cannot instantiate abstract class "C" with abstract attribute "bar"
c.bar()
@abstractmethod
def bar(self) -> None:
pass
6 changes: 3 additions & 3 deletions test-data/unit/check-functools.test
Original file line number Diff line number Diff line change
@@ -586,9 +586,9 @@ class A(ABC):
def method(self) -> None: ...

def f1(cls: type[A]) -> None:
cls()
partial_cls = partial(cls)
partial_cls()
cls() # E: Cannot instantiate abstract class "A" with abstract attribute "method"
partial_cls = partial(cls) # E: Cannot instantiate abstract class "A" with abstract attribute "method"
partial_cls() # E: Cannot instantiate abstract class "A" with abstract attribute "method"

def f2() -> None:
A() # E: Cannot instantiate abstract class "A" with abstract attribute "method"
10 changes: 5 additions & 5 deletions test-data/unit/check-protocols.test
Original file line number Diff line number Diff line change
@@ -1603,7 +1603,7 @@ class C:
pass

def f(cls: Type[P]) -> P:
return cls() # OK
return cls() # E: Cannot instantiate protocol class "P"
def g() -> P:
return P() # E: Cannot instantiate protocol class "P"

@@ -1625,7 +1625,7 @@ class C:
pass

def f(cls: Type[P]) -> P:
return cls() # OK
return cls() # E: Cannot instantiate protocol class "P"

Alias = P
GoodAlias = C
@@ -1646,14 +1646,14 @@ class C:
pass

var: Type[P]
var()
var() # E: Cannot instantiate protocol class "P"
if int():
var = P # E: Can only assign concrete classes to a variable of type "Type[P]"
var = B # OK
var = C # OK

var_old = None # type: Type[P] # Old syntax for variable annotations
var_old()
var_old() # E: Cannot instantiate protocol class "P"
if int():
var_old = P # E: Can only assign concrete classes to a variable of type "Type[P]"
var_old = B # OK
@@ -1669,7 +1669,7 @@ class Logger:
class C(Protocol):
@classmethod
def action(cls) -> None:
cls() #OK for classmethods
cls() # E: Cannot instantiate protocol class "C"
Logger.log(cls) #OK for classmethods
[builtins fixtures/classmethod.pyi]

2 changes: 1 addition & 1 deletion test-data/unit/check-selftype.test
Original file line number Diff line number Diff line change
@@ -1023,7 +1023,7 @@ T = TypeVar('T', bound=HasX)
class Meta(type):
def do_x(cls: Type[T]) -> T:
cls.x
return cls()
return cls() # E: Cannot instantiate protocol class "HasX"

class Good(metaclass=Meta):
x: int