diff --git a/mypy/main.py b/mypy/main.py index dff1a0362ba2..718eb5a7c0c1 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -999,15 +999,6 @@ def add_invertible_flag( action="store_true", help="Enable new experimental type inference algorithm", ) - internals_group.add_argument( - "--disable-recursive-aliases", - action="store_true", - help="Disable experimental support for recursive type aliases", - ) - # Deprecated reverse variant of the above. - internals_group.add_argument( - "--enable-recursive-aliases", action="store_true", help=argparse.SUPPRESS - ) parser.add_argument( "--enable-incomplete-feature", action="append", @@ -1392,11 +1383,6 @@ def set_strict_flags() -> None: if options.logical_deps: options.cache_fine_grained = True - if options.enable_recursive_aliases: - print( - "Warning: --enable-recursive-aliases is deprecated;" - " recursive types are enabled by default" - ) if options.strict_concatenate and not strict_option_set: print("Warning: --strict-concatenate is deprecated; use --extra-checks instead") diff --git a/mypy/options.py b/mypy/options.py index cb0464d4dc06..3447b5dfb1f6 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -362,10 +362,6 @@ def __init__(self) -> None: self.many_errors_threshold = defaults.MANY_ERRORS_THRESHOLD # Enable new experimental type inference algorithm. self.new_type_inference = False - # Disable recursive type aliases (currently experimental) - self.disable_recursive_aliases = False - # Deprecated reverse version of the above, do not use. - self.enable_recursive_aliases = False # Export line-level, limited, fine-grained dependency information in cache data # (undocumented feature). self.export_ref_info = False diff --git a/mypy/semanal.py b/mypy/semanal.py index a114a5a1dcd4..27491ac695ae 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3608,7 +3608,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: ) if not res: return False - if not self.options.disable_recursive_aliases and not self.is_func_scope(): + if not self.is_func_scope(): # Only marking incomplete for top-level placeholders makes recursive aliases like # `A = Sequence[str | A]` valid here, similar to how we treat base classes in class # definitions, allowing `class str(Sequence[str]): ...` @@ -6296,7 +6296,7 @@ def process_placeholder( def cannot_resolve_name(self, name: str | None, kind: str, ctx: Context) -> None: name_format = f' "{name}"' if name else "" self.fail(f"Cannot resolve {kind}{name_format} (possible cyclic definition)", ctx) - if not self.options.disable_recursive_aliases and self.is_func_scope(): + if self.is_func_scope(): self.note("Recursive types are not allowed at function scope", ctx) def qualified_name(self, name: str) -> str: diff --git a/mypy/semanal_namedtuple.py b/mypy/semanal_namedtuple.py index 51ea90e07f3d..80cf1c4e184a 100644 --- a/mypy/semanal_namedtuple.py +++ b/mypy/semanal_namedtuple.py @@ -182,8 +182,7 @@ def check_namedtuple_classdef( # it would be inconsistent with type aliases. analyzed = self.api.anal_type( stmt.type, - allow_placeholder=not self.options.disable_recursive_aliases - and not self.api.is_func_scope(), + allow_placeholder=not self.api.is_func_scope(), prohibit_self_type="NamedTuple item type", ) if analyzed is None: @@ -450,8 +449,7 @@ def parse_namedtuple_fields_with_types( # We never allow recursive types at function scope. analyzed = self.api.anal_type( type, - allow_placeholder=not self.options.disable_recursive_aliases - and not self.api.is_func_scope(), + allow_placeholder=not self.api.is_func_scope(), prohibit_self_type="NamedTuple item type", ) # Workaround #4987 and avoid introducing a bogus UnboundType diff --git a/mypy/semanal_newtype.py b/mypy/semanal_newtype.py index 16c6c024800d..c9c0c46f7aee 100644 --- a/mypy/semanal_newtype.py +++ b/mypy/semanal_newtype.py @@ -207,8 +207,7 @@ def check_newtype_args( self.api.anal_type( unanalyzed_type, report_invalid_types=False, - allow_placeholder=not self.options.disable_recursive_aliases - and not self.api.is_func_scope(), + allow_placeholder=not self.api.is_func_scope(), ) ) should_defer = False diff --git a/mypy/semanal_typeddict.py b/mypy/semanal_typeddict.py index a9a4cd868f27..51424d8800d2 100644 --- a/mypy/semanal_typeddict.py +++ b/mypy/semanal_typeddict.py @@ -228,10 +228,7 @@ def analyze_base_args(self, base: IndexExpr, ctx: Context) -> list[Type] | None: self.fail("Invalid TypedDict type argument", ctx) return None analyzed = self.api.anal_type( - type, - allow_required=True, - allow_placeholder=not self.options.disable_recursive_aliases - and not self.api.is_func_scope(), + type, allow_required=True, allow_placeholder=not self.api.is_func_scope() ) if analyzed is None: return None @@ -307,8 +304,7 @@ def analyze_typeddict_classdef_fields( analyzed = self.api.anal_type( stmt.type, allow_required=True, - allow_placeholder=not self.options.disable_recursive_aliases - and not self.api.is_func_scope(), + allow_placeholder=not self.api.is_func_scope(), prohibit_self_type="TypedDict item type", ) if analyzed is None: @@ -504,8 +500,7 @@ def parse_typeddict_fields_with_types( analyzed = self.api.anal_type( type, allow_required=True, - allow_placeholder=not self.options.disable_recursive_aliases - and not self.api.is_func_scope(), + allow_placeholder=not self.api.is_func_scope(), prohibit_self_type="TypedDict item type", ) if analyzed is None: diff --git a/mypy/typeanal.py b/mypy/typeanal.py index ceb276d3bdd4..03579404aac9 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -490,7 +490,7 @@ def cannot_resolve_type(self, t: UnboundType) -> None: # need access to MessageBuilder here. Also move the similar # message generation logic in semanal.py. self.api.fail(f'Cannot resolve name "{t.name}" (possible cyclic definition)', t) - if not self.options.disable_recursive_aliases and self.api.is_func_scope(): + if self.api.is_func_scope(): self.note("Recursive types are not allowed at function scope", t) def apply_concatenate_operator(self, t: UnboundType) -> Type: diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index cd60ec7c9a9c..983cb8454a05 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -5002,12 +5002,13 @@ class A(Tuple[int, str]): pass -- ----------------------- [case testCrashOnSelfRecursiveNamedTupleVar] -# flags: --disable-recursive-aliases from typing import NamedTuple -N = NamedTuple('N', [('x', N)]) # E: Cannot resolve name "N" (possible cyclic definition) -n: N -reveal_type(n) # N: Revealed type is "Tuple[Any, fallback=__main__.N]" +def test() -> None: + N = NamedTuple('N', [('x', N)]) # E: Cannot resolve name "N" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + n: N + reveal_type(n) # N: Revealed type is "Tuple[Any, fallback=__main__.N@4]" [builtins fixtures/tuple.pyi] [case testCrashOnSelfRecursiveTypedDictVar] @@ -5032,18 +5033,20 @@ lst = [n, m] [builtins fixtures/isinstancelist.pyi] [case testCorrectJoinOfSelfRecursiveTypedDicts] -# flags: --disable-recursive-aliases from mypy_extensions import TypedDict -class N(TypedDict): - x: N # E: Cannot resolve name "N" (possible cyclic definition) -class M(TypedDict): - x: M # E: Cannot resolve name "M" (possible cyclic definition) - -n: N -m: M -lst = [n, m] -reveal_type(lst[0]['x']) # N: Revealed type is "Any" +def test() -> None: + class N(TypedDict): + x: N # E: Cannot resolve name "N" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + class M(TypedDict): + x: M # E: Cannot resolve name "M" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + + n: N + m: M + lst = [n, m] + reveal_type(lst[0]['x']) # N: Revealed type is "Any" [builtins fixtures/isinstancelist.pyi] [case testCrashInForwardRefToNamedTupleWithIsinstance] diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 801bbd4e77b4..f2625b869c19 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -4594,7 +4594,6 @@ def outer() -> None: [out2] [case testRecursiveAliasImported] -# flags: --disable-recursive-aliases import a [file a.py] @@ -4620,16 +4619,10 @@ B = List[A] [builtins fixtures/list.pyi] [out] -tmp/lib.pyi:4: error: Module "other" has no attribute "B" -tmp/other.pyi:3: error: Cannot resolve name "B" (possible cyclic definition) [out2] -tmp/lib.pyi:4: error: Module "other" has no attribute "B" -tmp/other.pyi:3: error: Cannot resolve name "B" (possible cyclic definition) -tmp/a.py:3: note: Revealed type is "builtins.list[Any]" - -[case testRecursiveNamedTupleTypedDict-skip] -# https://github.com/python/mypy/issues/7125 +tmp/a.py:3: note: Revealed type is "builtins.list[builtins.list[...]]" +[case testRecursiveNamedTupleTypedDict] import a [file a.py] import lib @@ -4641,7 +4634,7 @@ reveal_type(x.x['x']) [file lib.pyi] from typing import NamedTuple from other import B -A = NamedTuple('A', [('x', B)]) # type: ignore +A = NamedTuple('A', [('x', B)]) [file other.pyi] from mypy_extensions import TypedDict from lib import A @@ -4649,7 +4642,7 @@ B = TypedDict('B', {'x': A}) [builtins fixtures/dict.pyi] [out] [out2] -tmp/a.py:3: note: Revealed type is "Tuple[TypedDict('other.B', {'x': Any}), fallback=lib.A]" +tmp/a.py:3: note: Revealed type is "Tuple[TypedDict('other.B', {'x': Tuple[..., fallback=lib.A]}), fallback=lib.A]" [case testFollowImportSkipNotInvalidatedOnPresent] # flags: --follow-imports=skip diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 9fa098b28dee..14e075339572 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -607,16 +607,18 @@ tmp/b.py:4: note: Revealed type is "Tuple[Any, fallback=a.N]" tmp/b.py:7: note: Revealed type is "Tuple[Any, fallback=a.N]" [case testSimpleSelfReferentialNamedTuple] -# flags: --disable-recursive-aliases from typing import NamedTuple -class MyNamedTuple(NamedTuple): - parent: 'MyNamedTuple' # E: Cannot resolve name "MyNamedTuple" (possible cyclic definition) -def bar(nt: MyNamedTuple) -> MyNamedTuple: - return nt +def test() -> None: + class MyNamedTuple(NamedTuple): + parent: 'MyNamedTuple' # E: Cannot resolve name "MyNamedTuple" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope -x: MyNamedTuple -reveal_type(x.parent) # N: Revealed type is "Any" + def bar(nt: MyNamedTuple) -> MyNamedTuple: + return nt + + x: MyNamedTuple + reveal_type(x.parent) # N: Revealed type is "Any" [builtins fixtures/tuple.pyi] -- Some crazy self-referential named tuples and types dicts @@ -645,106 +647,111 @@ class B: [out] [case testSelfRefNT1] -# flags: --disable-recursive-aliases from typing import Tuple, NamedTuple -Node = NamedTuple('Node', [ - ('name', str), - ('children', Tuple['Node', ...]), # E: Cannot resolve name "Node" (possible cyclic definition) - ]) -n: Node -reveal_type(n) # N: Revealed type is "Tuple[builtins.str, builtins.tuple[Any, ...], fallback=__main__.Node]" +def test() -> None: + Node = NamedTuple('Node', [ + ('name', str), + ('children', Tuple['Node', ...]), # E: Cannot resolve name "Node" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + ]) + n: Node + reveal_type(n) # N: Revealed type is "Tuple[builtins.str, builtins.tuple[Any, ...], fallback=__main__.Node@4]" [builtins fixtures/tuple.pyi] [case testSelfRefNT2] -# flags: --disable-recursive-aliases from typing import Tuple, NamedTuple -A = NamedTuple('A', [ - ('x', str), - ('y', Tuple['B', ...]), # E: Cannot resolve name "B" (possible cyclic definition) - ]) -class B(NamedTuple): - x: A - y: int +def test() -> None: + A = NamedTuple('A', [ + ('x', str), + ('y', Tuple['B', ...]), # E: Cannot resolve name "B" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + ]) + class B(NamedTuple): + x: A + y: int -n: A -reveal_type(n) # N: Revealed type is "Tuple[builtins.str, builtins.tuple[Any, ...], fallback=__main__.A]" + n: A + reveal_type(n) # N: Revealed type is "Tuple[builtins.str, builtins.tuple[Any, ...], fallback=__main__.A@4]" [builtins fixtures/tuple.pyi] [case testSelfRefNT3] -# flags: --disable-recursive-aliases from typing import NamedTuple, Tuple -class B(NamedTuple): - x: Tuple[A, int] # E: Cannot resolve name "A" (possible cyclic definition) - y: int +def test() -> None: + class B(NamedTuple): + x: Tuple[A, int] # E: Cannot resolve name "A" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + y: int -A = NamedTuple('A', [ - ('x', str), - ('y', 'B'), - ]) -n: B -m: A -reveal_type(n.x) # N: Revealed type is "Tuple[Any, builtins.int]" -reveal_type(m[0]) # N: Revealed type is "builtins.str" -lst = [m, n] -reveal_type(lst[0]) # N: Revealed type is "Tuple[builtins.object, builtins.object]" + A = NamedTuple('A', [ + ('x', str), + ('y', 'B'), + ]) + n: B + m: A + reveal_type(n.x) # N: Revealed type is "Tuple[Any, builtins.int]" + reveal_type(m[0]) # N: Revealed type is "builtins.str" + lst = [m, n] + reveal_type(lst[0]) # N: Revealed type is "Tuple[builtins.object, builtins.object]" [builtins fixtures/tuple.pyi] [case testSelfRefNT4] -# flags: --disable-recursive-aliases from typing import NamedTuple -class B(NamedTuple): - x: A # E: Cannot resolve name "A" (possible cyclic definition) - y: int +def test() -> None: + class B(NamedTuple): + x: A # E: Cannot resolve name "A" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + y: int -class A(NamedTuple): - x: str - y: B + class A(NamedTuple): + x: str + y: B -n: A -reveal_type(n.y[0]) # N: Revealed type is "Any" + n: A + reveal_type(n.y[0]) # N: Revealed type is "Any" [builtins fixtures/tuple.pyi] [case testSelfRefNT5] -# flags: --disable-recursive-aliases from typing import NamedTuple -B = NamedTuple('B', [ - ('x', A), # E: Cannot resolve name "A" (possible cyclic definition) # E: Name "A" is used before definition - ('y', int), - ]) -A = NamedTuple('A', [ - ('x', str), - ('y', 'B'), - ]) -n: A -def f(m: B) -> None: pass -reveal_type(n) # N: Revealed type is "Tuple[builtins.str, Tuple[Any, builtins.int, fallback=__main__.B], fallback=__main__.A]" -reveal_type(f) # N: Revealed type is "def (m: Tuple[Any, builtins.int, fallback=__main__.B])" +def test() -> None: + B = NamedTuple('B', [ + ('x', A), # E: Cannot resolve name "A" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope \ + # E: Name "A" is used before definition + ('y', int), + ]) + A = NamedTuple('A', [ + ('x', str), + ('y', 'B'), + ]) + n: A + def f(m: B) -> None: pass + reveal_type(n) # N: Revealed type is "Tuple[builtins.str, Tuple[Any, builtins.int, fallback=__main__.B@4], fallback=__main__.A@8]" + reveal_type(f) # N: Revealed type is "def (m: Tuple[Any, builtins.int, fallback=__main__.B@4])" [builtins fixtures/tuple.pyi] [case testRecursiveNamedTupleInBases] -# flags: --disable-recursive-aliases from typing import List, NamedTuple, Union -Exp = Union['A', 'B'] # E: Cannot resolve name "Exp" (possible cyclic definition) \ - # E: Cannot resolve name "A" (possible cyclic definition) -class A(NamedTuple('A', [('attr', List[Exp])])): pass -class B(NamedTuple('B', [('val', object)])): pass +def test() -> None: + Exp = Union['A', 'B'] # E: Cannot resolve name "Exp" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope \ + # E: Cannot resolve name "A" (possible cyclic definition) + class A(NamedTuple('A', [('attr', List[Exp])])): pass + class B(NamedTuple('B', [('val', object)])): pass -def my_eval(exp: Exp) -> int: - reveal_type(exp) # N: Revealed type is "Union[Any, Tuple[builtins.object, fallback=__main__.B]]" + exp: Exp + reveal_type(exp) # N: Revealed type is "Union[Any, Tuple[builtins.object, fallback=__main__.B@6]]" if isinstance(exp, A): - my_eval(exp[0][0]) - return my_eval(exp.attr[0]) + reveal_type(exp[0][0]) # N: Revealed type is "Union[Any, Tuple[builtins.object, fallback=__main__.B@6]]" + reveal_type(exp.attr[0]) # N: Revealed type is "Union[Any, Tuple[builtins.object, fallback=__main__.B@6]]" if isinstance(exp, B): - return exp.val # E: Incompatible return value type (got "object", expected "int") - return 0 - -my_eval(A([B(1), B(2)])) # OK + reveal_type(exp.val) # N: Revealed type is "builtins.object" + reveal_type(A([B(1), B(2)])) # N: Revealed type is "Tuple[builtins.list[Union[Any, Tuple[builtins.object, fallback=__main__.B@6]]], fallback=__main__.A@5]" [builtins fixtures/isinstancelist.pyi] [out] @@ -771,17 +778,18 @@ tp = NamedTuple('tp', [('x', int)]) [out] [case testSubclassOfRecursiveNamedTuple] -# flags: --disable-recursive-aliases from typing import List, NamedTuple -class Command(NamedTuple): - subcommands: List['Command'] # E: Cannot resolve name "Command" (possible cyclic definition) +def test() -> None: + class Command(NamedTuple): + subcommands: List['Command'] # E: Cannot resolve name "Command" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope -class HelpCommand(Command): - pass + class HelpCommand(Command): + pass -hc = HelpCommand(subcommands=[]) -reveal_type(hc) # N: Revealed type is "Tuple[builtins.list[Any], fallback=__main__.HelpCommand]" + hc = HelpCommand(subcommands=[]) + reveal_type(hc) # N: Revealed type is "Tuple[builtins.list[Any], fallback=__main__.HelpCommand@7]" [builtins fixtures/list.pyi] [out] diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index ff8d346e74a1..f4d3b9df760e 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -434,13 +434,14 @@ def main() -> None: x # E: Name "x" is not defined [case testNewAnalyzerCyclicDefinitions] -# flags: --disable-recursive-aliases --disable-error-code used-before-def +# flags: --disable-error-code used-before-def gx = gy # E: Cannot resolve name "gy" (possible cyclic definition) gy = gx def main() -> None: class C: def meth(self) -> None: - lx = ly # E: Cannot resolve name "ly" (possible cyclic definition) + lx = ly # E: Cannot resolve name "ly" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope ly = lx [case testNewAnalyzerCyclicDefinitionCrossModule] @@ -1495,22 +1496,25 @@ reveal_type(x[0][0]) # N: Revealed type is "__main__.C" [builtins fixtures/list.pyi] [case testNewAnalyzerAliasToNotReadyDirectBase] -# flags: --disable-recursive-aliases --disable-error-code used-before-def +# flags: --disable-error-code used-before-def from typing import List -x: B -B = List[C] -class C(B): pass +def test() -> None: + x: B + B = List[C] + class C(B): pass -reveal_type(x) -reveal_type(x[0][0]) + reveal_type(x) + reveal_type(x[0][0]) [builtins fixtures/list.pyi] [out] -main:4: error: Cannot resolve name "B" (possible cyclic definition) main:5: error: Cannot resolve name "B" (possible cyclic definition) -main:5: error: Cannot resolve name "C" (possible cyclic definition) -main:8: note: Revealed type is "Any" +main:5: note: Recursive types are not allowed at function scope +main:6: error: Cannot resolve name "B" (possible cyclic definition) +main:6: note: Recursive types are not allowed at function scope +main:6: error: Cannot resolve name "C" (possible cyclic definition) main:9: note: Revealed type is "Any" +main:10: note: Revealed type is "Any" [case testNewAnalyzerAliasToNotReadyTwoDeferralsFunction] # flags: --disable-error-code used-before-def @@ -1530,25 +1534,21 @@ reveal_type(f) # N: Revealed type is "def (x: builtins.list[a.C]) -> builtins.l [builtins fixtures/list.pyi] [case testNewAnalyzerAliasToNotReadyDirectBaseFunction] -# flags: --disable-recursive-aliases --disable-error-code used-before-def +# flags: --disable-error-code used-before-def import a [file a.py] from typing import List from b import D def f(x: B) -> List[B]: ... -B = List[C] # E +B = List[C] class C(B): pass [file b.py] from a import f class D: ... -reveal_type(f) # N +reveal_type(f) # N: Revealed type is "def (x: builtins.list[a.C]) -> builtins.list[builtins.list[a.C]]" [builtins fixtures/list.pyi] -[out] -tmp/b.py:3: note: Revealed type is "def (x: builtins.list[Any]) -> builtins.list[builtins.list[Any]]" -tmp/a.py:5: error: Cannot resolve name "B" (possible cyclic definition) -tmp/a.py:5: error: Cannot resolve name "C" (possible cyclic definition) [case testNewAnalyzerAliasToNotReadyMixed] from typing import List, Union @@ -2118,25 +2118,29 @@ class B(List[C]): [builtins fixtures/list.pyi] [case testNewAnalyzerNewTypeForwardClassAliasDirect] -# flags: --disable-recursive-aliases --disable-error-code used-before-def +# flags: --disable-error-code used-before-def from typing import NewType, List -x: D -reveal_type(x[0][0]) +def test() -> None: + x: D + reveal_type(x[0][0]) -D = List[C] -C = NewType('C', 'B') + D = List[C] + C = NewType('C', 'B') -class B(D): - pass + class B(D): + pass [builtins fixtures/list.pyi] [out] -main:4: error: Cannot resolve name "D" (possible cyclic definition) -main:5: note: Revealed type is "Any" -main:7: error: Cannot resolve name "D" (possible cyclic definition) -main:7: error: Cannot resolve name "C" (possible cyclic definition) -main:8: error: Argument 2 to NewType(...) must be a valid type -main:8: error: Cannot resolve name "B" (possible cyclic definition) +main:5: error: Cannot resolve name "D" (possible cyclic definition) +main:5: note: Recursive types are not allowed at function scope +main:6: note: Revealed type is "Any" +main:8: error: Cannot resolve name "D" (possible cyclic definition) +main:8: note: Recursive types are not allowed at function scope +main:8: error: Cannot resolve name "C" (possible cyclic definition) +main:9: error: Argument 2 to NewType(...) must be a valid type +main:9: error: Cannot resolve name "B" (possible cyclic definition) +main:9: note: Recursive types are not allowed at function scope -- Copied from check-classes.test (tricky corner cases). [case testNewAnalyzerNoCrashForwardRefToBrokenDoubleNewTypeClass] @@ -2154,22 +2158,24 @@ class C: [builtins fixtures/dict.pyi] [case testNewAnalyzerForwardTypeAliasInBase] -# flags: --disable-recursive-aliases from typing import List, Generic, TypeVar, NamedTuple T = TypeVar('T') -class C(A, B): # E: Cannot resolve name "A" (possible cyclic definition) - pass -class G(Generic[T]): pass -A = G[C] # E: Cannot resolve name "A" (possible cyclic definition) -class B(NamedTuple): - x: int +def test() -> None: + class C(A, B): # E: Cannot resolve name "A" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + pass + class G(Generic[T]): pass + A = G[C] # E: Cannot resolve name "A" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + class B(NamedTuple): + x: int -y: C -reveal_type(y.x) # N: Revealed type is "builtins.int" -reveal_type(y[0]) # N: Revealed type is "builtins.int" -x: A -reveal_type(x) # N: Revealed type is "__main__.G[Tuple[builtins.int, fallback=__main__.C]]" + y: C + reveal_type(y.x) # N: Revealed type is "builtins.int" + reveal_type(y[0]) # N: Revealed type is "builtins.int" + x: A + reveal_type(x) # N: Revealed type is "__main__.G@7[Tuple[builtins.int, fallback=__main__.C@5]]" [builtins fixtures/list.pyi] [case testNewAnalyzerDuplicateTypeVar] @@ -2584,9 +2590,9 @@ import n def __getattr__(x): pass [case testNewAnalyzerReportLoopInMRO2] -# flags: --disable-recursive-aliases def f() -> None: - class A(A): ... # E: Cannot resolve name "A" (possible cyclic definition) + class A(A): ... # E: Cannot resolve name "A" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope [case testNewAnalyzerUnsupportedBaseClassInsideFunction] class C: diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 3ca0c5ef0a4b..46f5ff07f1ac 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -197,30 +197,35 @@ Alias = Tuple[int, T] [out] [case testRecursiveAliasesErrors1] -# flags: --disable-recursive-aliases -# Recursive aliases are not supported yet. from typing import Type, Callable, Union -A = Union[A, int] # E: Cannot resolve name "A" (possible cyclic definition) -B = Callable[[B], int] # E: Cannot resolve name "B" (possible cyclic definition) -C = Type[C] # E: Cannot resolve name "C" (possible cyclic definition) +def test() -> None: + A = Union[A, int] # E: Cannot resolve name "A" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + B = Callable[[B], int] # E: Cannot resolve name "B" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + C = Type[C] # E: Cannot resolve name "C" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope [case testRecursiveAliasesErrors2] -# flags: --disable-recursive-aliases --disable-error-code=used-before-def -# Recursive aliases are not supported yet. +# flags: --disable-error-code=used-before-def from typing import Type, Callable, Union -A = Union[B, int] -B = Callable[[C], int] -C = Type[A] -x: A -reveal_type(x) +def test() -> None: + A = Union[B, int] + B = Callable[[C], int] + C = Type[A] + x: A + reveal_type(x) [out] main:5: error: Cannot resolve name "A" (possible cyclic definition) +main:5: note: Recursive types are not allowed at function scope main:5: error: Cannot resolve name "B" (possible cyclic definition) main:6: error: Cannot resolve name "B" (possible cyclic definition) +main:6: note: Recursive types are not allowed at function scope main:6: error: Cannot resolve name "C" (possible cyclic definition) main:7: error: Cannot resolve name "C" (possible cyclic definition) +main:7: note: Recursive types are not allowed at function scope main:9: note: Revealed type is "Union[Any, builtins.int]" [case testDoubleForwardAlias] @@ -245,13 +250,16 @@ reveal_type(x[0].x) # N: Revealed type is "builtins.str" [out] [case testJSONAliasApproximation] -# flags: --disable-recursive-aliases from typing import List, Union, Dict -x: JSON # E: Cannot resolve name "JSON" (possible cyclic definition) -JSON = Union[int, str, List[JSON], Dict[str, JSON]] # E: Cannot resolve name "JSON" (possible cyclic definition) -reveal_type(x) # N: Revealed type is "Any" -if isinstance(x, list): - reveal_type(x) # N: Revealed type is "builtins.list[Any]" + +def test() -> None: + x: JSON # E: Cannot resolve name "JSON" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + JSON = Union[int, str, List[JSON], Dict[str, JSON]] # E: Cannot resolve name "JSON" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + reveal_type(x) # N: Revealed type is "Any" + if isinstance(x, list): + reveal_type(x) # N: Revealed type is "builtins.list[Any]" [builtins fixtures/isinstancelist.pyi] [out] diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 0e1d800e0468..088b52db0473 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -1443,34 +1443,34 @@ reveal_type(x['a']['b']) # N: Revealed type is "builtins.int" [builtins fixtures/dict.pyi] [case testSelfRecursiveTypedDictInheriting] - from mypy_extensions import TypedDict -# flags: --disable-recursive-aliases -class MovieBase(TypedDict): - name: str - year: int -class Movie(MovieBase): - director: 'Movie' # E: Cannot resolve name "Movie" (possible cyclic definition) +def test() -> None: + class MovieBase(TypedDict): + name: str + year: int -m: Movie -reveal_type(m['director']['name']) # N: Revealed type is "Any" + class Movie(MovieBase): + director: 'Movie' # E: Cannot resolve name "Movie" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope + m: Movie + reveal_type(m['director']['name']) # N: Revealed type is "Any" [builtins fixtures/dict.pyi] -[out] [case testSubclassOfRecursiveTypedDict] -# flags: --disable-recursive-aliases from typing import List from mypy_extensions import TypedDict -class Command(TypedDict): - subcommands: List['Command'] # E: Cannot resolve name "Command" (possible cyclic definition) +def test() -> None: + class Command(TypedDict): + subcommands: List['Command'] # E: Cannot resolve name "Command" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope -class HelpCommand(Command): - pass + class HelpCommand(Command): + pass -hc = HelpCommand(subcommands=[]) -reveal_type(hc) # N: Revealed type is "TypedDict('__main__.HelpCommand', {'subcommands': builtins.list[Any]})" + hc = HelpCommand(subcommands=[]) + reveal_type(hc) # N: Revealed type is "TypedDict('__main__.HelpCommand@8', {'subcommands': builtins.list[Any]})" [builtins fixtures/list.pyi] [out] diff --git a/test-data/unit/check-unions.test b/test-data/unit/check-unions.test index f6fd27e59e4d..d79ab14184c6 100644 --- a/test-data/unit/check-unions.test +++ b/test-data/unit/check-unions.test @@ -1003,9 +1003,11 @@ def takes_int(arg: int) -> None: pass takes_int(x) # E: Argument 1 to "takes_int" has incompatible type "Union[ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[int], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[object], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[float], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[str], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[Any], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[bytes]]"; expected "int" [case testRecursiveForwardReferenceInUnion] -# flags: --disable-recursive-aliases from typing import List, Union -MYTYPE = List[Union[str, "MYTYPE"]] # E: Cannot resolve name "MYTYPE" (possible cyclic definition) + +def test() -> None: + MYTYPE = List[Union[str, "MYTYPE"]] # E: Cannot resolve name "MYTYPE" (possible cyclic definition) \ + # N: Recursive types are not allowed at function scope [builtins fixtures/list.pyi] [case testNonStrictOptional] diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 42f0ee8a9ec6..cf5e3c438fac 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -1472,14 +1472,6 @@ note: A user-defined top-level module with name "typing" is not supported Failed to find builtin module mypy_extensions, perhaps typeshed is broken? == Return code: 2 -[case testRecursiveAliasesFlagDeprecated] -# cmd: mypy --enable-recursive-aliases a.py -[file a.py] -pass -[out] -Warning: --enable-recursive-aliases is deprecated; recursive types are enabled by default -== Return code: 0 - [case testNotesOnlyResultInExitSuccess] # cmd: mypy a.py [file a.py]