Repository: python/mypy

Issue:
Setting 'item' attribute as an instance created earlier leads to an internal error 
The code sets up a class with a 'NamedTuple' type and initializes an instance of that class with a specified field. The "item" attribute of the instance holds an instance of NamedTuple created earlier. Mypy reports an internal error.

Example.py
```
from typing import NamedTuple
class Test:
    def __init__(self, field):
        self.Item = NamedTuple("x", [(field, str)])
        self.item: self.Item
```

### The expected behavior:
It does not report an internal error.


### The actual behavior: 
```
/home/xxm/Desktop/example.py:7: error: INTERNAL ERROR -- Please try using mypy master on GitHub:
https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 1.4.0+dev.66bd2c441277b29b1454e26b2a3454a0dae5fb18
Traceback (most recent call last):
  File "/home/xxm/.local/bin/mypy", line 8, in <module>
    sys.exit(console_entry())
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/__main__.py", line 15, in console_entry
    main()
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/main.py", line 95, in main
    res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/main.py", line 174, in run_build
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/build.py", line 194, in build
    result = _build(
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/build.py", line 267, in _build
    graph = dispatch(sources, manager, stdout)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/build.py", line 2926, in dispatch
    process_graph(graph, manager)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/build.py", line 3324, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/build.py", line 3419, in process_stale_scc
    mypy.semanal_main.semantic_analysis_for_scc(graph, scc, manager.errors)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal_main.py", line 95, in semantic_analysis_for_scc
    process_functions(graph, scc, patches)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal_main.py", line 253, in process_functions
    process_top_level_function(
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal_main.py", line 292, in process_top_level_function
    deferred, incomplete, progress = semantic_analyze_target(
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal_main.py", line 350, in semantic_analyze_target
    analyzer.refresh_partial(
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal.py", line 603, in refresh_partial
    self.accept(node)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal.py", line 6352, in accept
    node.accept(self)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/nodes.py", line 786, in accept
    return visitor.visit_func_def(self)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal.py", line 833, in visit_func_def
    self.analyze_func_def(defn)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal.py", line 897, in analyze_func_def
    self.analyze_function_body(defn)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal.py", line 1390, in analyze_function_body
    defn.body.accept(self)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/nodes.py", line 1220, in accept
    return visitor.visit_block(self)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal.py", line 4562, in visit_block
    self.accept(s)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal.py", line 6352, in accept
    node.accept(self)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/nodes.py", line 1307, in accept
    return visitor.visit_assignment_stmt(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal.py", line 2824, in visit_assignment_stmt
    self.record_special_form_lvalue(s)
  File "/home/xxm/.local/lib/python3.11/site-packages/mypy/semanal.py", line 3045, in record_special_form_lvalue
    assert isinstance(lvalue, NameExpr)
AssertionError: 
/home/xxm/Desktop/example.py:7: : note: use --pdb to drop into pdb
```

### Test environment:

Mypy version: 1.4.0+ (master)
Python version: 3.11.3
Operating System: Ubuntu 18.04
How to install MyPy: "python3 -m pip install -U git+https://github.com/python/mypy.git"





Discussion:

Resolving patch:
diff --git a/mypy/semanal.py b/mypy/semanal.py
--- a/mypy/semanal.py
+++ b/mypy/semanal.py
@@ -3067,6 +3067,12 @@ def analyze_namedtuple_assign(self, s: AssignmentStmt) -> bool:
         if len(s.lvalues) != 1 or not isinstance(s.lvalues[0], (NameExpr, MemberExpr)):
             return False
         lvalue = s.lvalues[0]
+        if isinstance(lvalue, MemberExpr):
+            if isinstance(s.rvalue, CallExpr) and isinstance(s.rvalue.callee, RefExpr):
+                fullname = s.rvalue.callee.fullname
+                if fullname == "collections.namedtuple" or fullname in TYPED_NAMEDTUPLE_NAMES:
+                    self.fail("NamedTuple type as an attribute is not supported", lvalue)
+            return False
         name = lvalue.name
         namespace = self.qualified_name(name)
         with self.tvar_scope_frame(self.tvar_scope.class_frame(namespace)):
@@ -3075,9 +3081,6 @@ def analyze_namedtuple_assign(self, s: AssignmentStmt) -> bool:
             )
             if internal_name is None:
                 return False
-            if isinstance(lvalue, MemberExpr):
-                self.fail("NamedTuple type as an attribute is not supported", lvalue)
-                return False
             if internal_name != name:
                 self.fail(
                     'First argument to namedtuple() should be "{}", not "{}"'.format(


Test patch:
diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test
--- a/test-data/unit/check-namedtuple.test
+++ b/test-data/unit/check-namedtuple.test
@@ -938,8 +938,9 @@ class A:
     def __init__(self) -> None:
         self.b = NamedTuple('x', [('s', str), ('n', int)])  # E: NamedTuple type as an attribute is not supported
 
-reveal_type(A().b)  # N: Revealed type is "Any"
+reveal_type(A().b)  # N: Revealed type is "typing.NamedTuple"
 [builtins fixtures/tuple.pyi]
+[typing fixtures/typing-namedtuple.pyi]
 
 [case testNamedTupleWrongfile]
 from typing import NamedTuple
@@ -983,7 +984,7 @@ class Both2(Other, Bar): ...
 class Both3(Biz, Other): ...
 
 def print_namedtuple(obj: NamedTuple) -> None:
-    reveal_type(obj.name)  # N: Revealed type is "builtins.str"
+    reveal_type(obj._fields)  # N: Revealed type is "builtins.tuple[builtins.str, ...]"
 
 b1: Bar
 b2: Baz
@@ -1337,3 +1338,12 @@ class SNT(NT[int]): ...
 reveal_type(SNT("test", 42).meth())  # N: Revealed type is "Tuple[builtins.str, builtins.int, fallback=__main__.SNT]"
 [builtins fixtures/tuple.pyi]
 [typing fixtures/typing-namedtuple.pyi]
+
+[case testNoCrashUnsupportedNamedTuple]
+from typing import NamedTuple
+class Test:
+    def __init__(self, field) -> None:
+        self.Item = NamedTuple("x", [(field, str)])  # E: NamedTuple type as an attribute is not supported
+        self.item: self.Item  # E: Name "self.Item" is not defined
+[builtins fixtures/tuple.pyi]
+[typing fixtures/typing-namedtuple.pyi]