Skip to content
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

Remove TypeType exception for abstract instantiation #18094

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
Expand Up @@ -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()
Expand Down
20 changes: 8 additions & 12 deletions test-data/unit/check-abstract.test
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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():
Expand All @@ -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():
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions test-data/unit/check-functools.test
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
10 changes: 5 additions & 5 deletions test-data/unit/check-protocols.test
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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]

Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-selftype.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading