Repository: cython/cython

Issue:
[BUG] v3.0.4: Compiler crash in AnalyseExpressionsTransform
### Describe the bug

When compiling PyBoy, it immediately started failing when 3.0.4 was released.


The error will look like this on Python 3.11:
```
Error compiling Cython file:
------------------------------------------------------------
...
                        self.buf0[(yy+y) % 0xFF][(xx+x) % 0xFF] = COLOR
                else: # Draw body
                    self.buf0[(yy+y) % 0xFF][xx % 0xFF] = COLOR
                    for x in range(constants.COLS):
                        self.buf0[(yy+y) % 0xFF][(xx+x) % 0xFF] &= self.color
                    self.buf0[(yy+y) % 0xFF][(xx + constants.COLS) % 0xFF] = COLOR
                                            ^
------------------------------------------------------------

pyboy/plugins/debug.py:560:44: Compiler crash in AnalyseExpressionsTransform
```
https://github.com/Baekalfen/PyBoy/actions/runs/6552514964/job/17795971017

It looks like this on Python 3.10:
```
Compiler crash traceback from this point on:
  File "d:\a\pyboy\pyboy\.eggs\cython-3.0.4-py3.8.egg\Cython\Compiler\ExprNodes.py", line 4968, in analyse_types
    performance_hint(index.pos, "Index should be typed for more efficient access")
TypeError: performance_hint() missing 1 required positional argument: 'env'
```

### Code to reproduce the behaviour:

https://github.com/baekalfen/pyboy

### Expected behaviour

Seemingly all other versions work. Expectantly 0.29 through 3.0.3

### OS

Linux, Windows, macOS

### Python version

3.8, 3.9, 3.10, 3,11

### Cython version

3.0.4

### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -4908,7 +4908,6 @@ class MemoryViewIndexNode(BufferIndexNode):
 
     is_memview_index = True
     is_buffer_access = False
-    warned_untyped_idx = False
 
     def analyse_types(self, env, getting=True):
         # memoryviewslice indexing or slicing
@@ -4964,9 +4963,8 @@ def analyse_types(self, env, getting=True):
                         new_indices.append(value)
 
             elif index.type.is_int or index.type.is_pyobject:
-                if index.type.is_pyobject and not self.warned_untyped_idx:
-                    performance_hint(index.pos, "Index should be typed for more efficient access")
-                    MemoryViewIndexNode.warned_untyped_idx = True
+                if index.type.is_pyobject:
+                    performance_hint(index.pos, "Index should be typed for more efficient access", env)
 
                 self.is_memview_index = True
                 index = index.coerce_to(index_type, env)


Test patch:
diff --git a/tests/memoryview/memoryview.pyx b/tests/memoryview/memoryview.pyx
--- a/tests/memoryview/memoryview.pyx
+++ b/tests/memoryview/memoryview.pyx
@@ -1,4 +1,5 @@
 # mode: run
+# tag: perf_hints
 
 # Test declarations, behaviour and coercions of the memoryview type itself.
 
@@ -1298,3 +1299,21 @@ def test_assignment_typedef():
     y = x
     for v in y:
         print(v)
+
+def test_untyped_index(i):
+    """
+    >>> test_untyped_index(2)
+    3
+    >>> test_untyped_index(0)
+    5
+    >>> test_untyped_index(-1)
+    0
+    """
+    cdef int[6] arr
+    arr = [5, 4, 3, 2, 1, 0]
+    cdef int[:] mview_arr = arr
+    return mview_arr[i]  # should generate a performance hint
+
+_PERFORMANCE_HINTS = """
+1315:21: Index should be typed for more efficient access
+"""