From 750dee91f18bf92fd10c282be9406ff30d45ec42 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Fri, 26 May 2017 10:19:09 -0700 Subject: [PATCH] Allow NewType subclassing NewType. Use case: type hierarchy of IDs, all of which are integers at runtime, but we want to type-check distinctions between e.g. "id of User" and "id of Media", while still allowing some functions to take "any ID" (which is still a more specific type than "any integer"). --- mypy/semanal.py | 4 ---- test-data/unit/check-newtype.test | 32 ++++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index d16be31e8e18..e930c3706191 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1822,10 +1822,6 @@ def check_newtype_args(self, name: str, call: CallExpr, context: Context) -> Opt return None old_type = self.anal_type(unanalyzed_type) - if isinstance(old_type, Instance) and old_type.type.is_newtype: - self.fail("Argument 2 to NewType(...) cannot be another NewType", context) - has_failed = True - return None if has_failed else old_type def build_newtype_typeinfo(self, name: str, old_type: Type, base_type: Instance) -> TypeInfo: diff --git a/test-data/unit/check-newtype.test b/test-data/unit/check-newtype.test index 144c8fba04c3..32b25558c84f 100644 --- a/test-data/unit/check-newtype.test +++ b/test-data/unit/check-newtype.test @@ -155,6 +155,29 @@ y = Bar2(42) y = func3(x) [out] +[case testNewTypeWithNewType] +from typing import NewType +A = NewType('A', int) +B = NewType('B', A) +C = A +D = C +E = NewType('E', D) + +a = A(1) +b = B(a) +e = E(a) + +def funca(a: A) -> None: ... +def funcb(b: B) -> None: ... + +funca(a) +funca(b) +funca(e) +funcb(a) # E: Argument 1 to "funcb" has incompatible type "A"; expected "B" +funcb(b) +funcb(e) # E: Argument 1 to "funcb" has incompatible type "E"; expected "B" + +[out] -- Make sure NewType works as expected in a variety of different scopes/across files @@ -279,15 +302,6 @@ main:3: error: Argument 2 to NewType(...) must be subclassable (got T?) main:3: error: Invalid type "__main__.T" main:4: error: Invalid type "__main__.T" -[case testNewTypeWithNewTypeFails] -from typing import NewType -A = NewType('A', int) -B = NewType('B', A) # E: Argument 2 to NewType(...) cannot be another NewType -C = A -D = C -E = NewType('E', D) # E: Argument 2 to NewType(...) cannot be another NewType -[out] - [case testNewTypeRedefiningVariablesFails] from typing import NewType