From: Siu Kwan Lam <1929845+sklam@users.noreply.github.com>
Origin: https://github.com/numba/numba/pull/8545
Date: Wed, 26 Oct 2022 15:53:07 -0500
Subject: Unbreak python <3.11

---
 numba/core/byteflow.py          | 105 ++++++++++++++++++++++++++--------------
 numba/core/runtime/context.py   |   6 ++-
 numba/tests/test_withlifting.py |   4 --
 3 files changed, 73 insertions(+), 42 deletions(-)

diff --git a/numba/core/byteflow.py b/numba/core/byteflow.py
index 5a49f99..674fa0e 100644
--- a/numba/core/byteflow.py
+++ b/numba/core/byteflow.py
@@ -777,22 +777,43 @@ class TraceRunner(object):
         state.append(inst, value=val, res=res)
         state.push(res)
 
-    def op_RAISE_VARARGS(self, state, inst):
-        if inst.arg == 0:
-            exc = None
-            raise UnsupportedError(
-                "The re-raising of an exception is not yet supported.",
-                loc=self.get_debug_loc(inst.lineno),
-            )
-        elif inst.arg == 1:
-            exc = state.pop()
-        else:
-            raise ValueError("Multiple argument raise is not supported.")
-        state.append(inst, exc=exc)
+    if PYVERSION >= (3, 11):
+        def op_RAISE_VARARGS(self, state, inst):
+            if inst.arg == 0:
+                exc = None
+                raise UnsupportedError(
+                    "The re-raising of an exception is not yet supported.",
+                    loc=self.get_debug_loc(inst.lineno),
+                )
+            elif inst.arg == 1:
+                exc = state.pop()
+            else:
+                raise ValueError("Multiple argument raise is not supported.")
+            state.append(inst, exc=exc)
 
-        if state.has_active_try():
-            self.handle_try(state)
-        else:
+            if state.has_active_try():
+                self.handle_try(state)
+            else:
+                state.terminate()
+
+    else:
+        def op_RAISE_VARARGS(self, state, inst):
+            in_exc_block = any([
+                state.get_top_block("EXCEPT") is not None,
+                state.get_top_block("FINALLY") is not None
+            ])
+            if inst.arg == 0:
+                exc = None
+                if in_exc_block:
+                    raise UnsupportedError(
+                        "The re-raising of an exception is not yet supported.",
+                        loc=self.get_debug_loc(inst.lineno),
+                    )
+            elif inst.arg == 1:
+                exc = state.pop()
+            else:
+                raise ValueError("Multiple argument raise is not supported.")
+            state.append(inst, exc=exc)
             state.terminate()
 
     def op_BEGIN_FINALLY(self, state, inst):
@@ -903,6 +924,8 @@ class TraceRunner(object):
             end=None,
             reset_stack=False,
         )
+        # Forces a new block
+        # Fork to the body of the finally
         state.fork(
             pc=next,
             extra_block=state.make_block(
@@ -931,11 +954,12 @@ class TraceRunner(object):
             'FINALLY', state, next=inst.next, end=inst.get_jump_target(),
         )
 
-    def op_POP_EXCEPT(self, state, inst):
-        if PYVERSION == (3, 11):
+    if PYVERSION >= (3, 11):
+        def op_POP_EXCEPT(self, state, inst):
             state.pop()
 
-        else:
+    else:
+        def op_POP_EXCEPT(self, state, inst):
             blk = state.pop_block()
             if blk['kind'] not in {BlockKind('EXCEPT'), BlockKind('FINALLY')}:
                 raise UnsupportedError(
@@ -1379,22 +1403,30 @@ class TraceRunner(object):
         state.fork(pc=inst.next)
         state.fork(pc=inst.get_jump_target())
 
-    def op_RERAISE(self, state, inst):
-        # This isn't handled, but the state is set up anyway
-        exc = state.pop()
-        if inst.arg != 0:
-            state.pop()     # lasti
-        state.append(inst, exc=exc)
+    if PYVERSION >= (3, 11):
+        def op_RERAISE(self, state, inst):
+            # This isn't handled, but the state is set up anyway
+            exc = state.pop()
+            if inst.arg != 0:
+                state.pop()     # lasti
+            state.append(inst, exc=exc)
 
-        if state.has_active_try():
-            self.handle_try(state)
-        else:
+            if state.has_active_try():
+                self.handle_try(state)
+            else:
+                state.terminate()
+    else:
+        def op_RERAISE(self, state, inst):
+            # This isn't handled, but the state is set up anyway
+            exc = state.pop()
+            state.append(inst, exc=exc)
             state.terminate()
+ 
 
     # NOTE: Please see notes in `interpreter.py` surrounding the implementation
     # of LOAD_METHOD and CALL_METHOD.
 
-    if PYVERSION == (3, 11):
+    if PYVERSION >= (3, 11):
         def op_LOAD_METHOD(self, state, inst):
             item = state.pop()
             extra = state.make_null()
@@ -1665,14 +1697,15 @@ class State(object):
                 stack.append(self.make_temp())
         # Handle changes on the blockstack
         blockstack = list(self._blockstack)
-        # pop expired block in destination pc
-        while blockstack:
-            top = blockstack[-1]
-            end = top.get('end_offset') or top['end']
-            if pc >= end:
-                blockstack.pop()
-            else:
-                break
+        if PYVERSION >= (3, 11):
+            # pop expired block in destination pc
+            while blockstack:
+                top = blockstack[-1]
+                end = top.get('end_offset') or top['end']
+                if pc >= end:
+                    blockstack.pop()
+                else:
+                    break
 
         if extra_block:
             blockstack.append(extra_block)
diff --git a/numba/core/runtime/context.py b/numba/core/runtime/context.py
index a58d4df..1c01fac 100644
--- a/numba/core/runtime/context.py
+++ b/numba/core/runtime/context.py
@@ -3,6 +3,7 @@ import functools
 from llvmlite import ir
 
 from numba.core import types, cgutils, errors
+from numba.core.utils import PYVERSION
 
 
 class NRTContext(object):
@@ -382,8 +383,9 @@ class NRTContext(object):
         trystatus = cc.check_try_status(builder)
         excinfo = trystatus.excinfo
         has_raised = builder.not_(cgutils.is_null(builder, excinfo))
-        # with builder.if_then(has_raised):
-        #     self.eh_end_try(builder)
+        if PYVERSION < (3, 11):
+            with builder.if_then(has_raised):
+                self.eh_end_try(builder)
         return has_raised
 
     def eh_try(self, builder):
diff --git a/numba/tests/test_withlifting.py b/numba/tests/test_withlifting.py
index e72d2d3..e2d9051 100644
--- a/numba/tests/test_withlifting.py
+++ b/numba/tests/test_withlifting.py
@@ -1193,8 +1193,6 @@ class TestBogusContext(BaseTestWithLifting):
             )
 
     def test_invalid(self):
-        import dis
-        dis.dis(lift_invalid)
         the_ir = get_func_ir(lift_invalid)
 
         with self.assertRaises(errors.CompilerError) as raises:
@@ -1212,8 +1210,6 @@ class TestBogusContext(BaseTestWithLifting):
             with open('') as f:
                 pass
 
-        import dis
-        dis.dis(foo)
         with self.assertRaises(errors.UnsupportedError) as raises:
             foo()
 
