[Python-checkins] bpo-46841: Fix error message hacks in `GET_AWAITABLE` (GH-31664)

markshannon webhook-mailer at python.org
Fri Mar 4 07:41:46 EST 2022


https://github.com/python/cpython/commit/586b24d3be1aec5d2568b070a249b4d75e608782
commit: 586b24d3be1aec5d2568b070a249b4d75e608782
branch: main
author: Brandt Bucher <brandtbucher at microsoft.com>
committer: markshannon <mark at hotpy.org>
date: 2022-03-04T12:41:17Z
summary:

bpo-46841: Fix error message hacks in `GET_AWAITABLE` (GH-31664)

files:
A Misc/NEWS.d/next/Core and Builtins/2022-03-03-12-36-15.bpo-46841.apPev2.rst
M Doc/library/dis.rst
M Include/opcode.h
M Lib/importlib/_bootstrap_external.py
M Lib/opcode.py
M Python/ceval.c
M Python/compile.c
M Python/opcode_targets.h

diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index 3dac3911da276..65e888dc86a19 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -475,15 +475,24 @@ the original TOS1.
 
 **Coroutine opcodes**
 
-.. opcode:: GET_AWAITABLE
+.. opcode:: GET_AWAITABLE (where)
 
    Implements ``TOS = get_awaitable(TOS)``, where ``get_awaitable(o)``
    returns ``o`` if ``o`` is a coroutine object or a generator object with
    the CO_ITERABLE_COROUTINE flag, or resolves
    ``o.__await__``.
 
+    If the ``where`` operand is nonzero, it indicates where the instruction
+    occurs:
+
+    * ``1`` After a call to ``__aenter__``
+    * ``2`` After a call to ``__aexit__``
+
    .. versionadded:: 3.5
 
+   .. versionchanged:: 3.11
+      Previously, this instruction did not have an oparg.
+
 
 .. opcode:: GET_AITER
 
diff --git a/Include/opcode.h b/Include/opcode.h
index 110f8c3617140..1b9eeacdeab01 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -33,7 +33,6 @@ extern "C" {
 #define GET_YIELD_FROM_ITER              69
 #define PRINT_EXPR                       70
 #define LOAD_BUILD_CLASS                 71
-#define GET_AWAITABLE                    73
 #define LOAD_ASSERTION_ERROR             74
 #define RETURN_GENERATOR                 75
 #define LIST_TO_TUPLE                    82
@@ -86,6 +85,7 @@ extern "C" {
 #define POP_JUMP_IF_NOT_NONE            128
 #define POP_JUMP_IF_NONE                129
 #define RAISE_VARARGS                   130
+#define GET_AWAITABLE                   131
 #define MAKE_FUNCTION                   132
 #define BUILD_SLICE                     133
 #define JUMP_NO_INTERRUPT               134
@@ -160,13 +160,13 @@ extern "C" {
 #define PRECALL_BUILTIN_FAST_WITH_KEYWORDS  66
 #define PRECALL_NO_KW_LEN                67
 #define PRECALL_NO_KW_ISINSTANCE         72
-#define PRECALL_NO_KW_LIST_APPEND        76
-#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O  77
-#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS  78
-#define PRECALL_NO_KW_STR_1              79
-#define PRECALL_NO_KW_TUPLE_1            80
-#define PRECALL_NO_KW_TYPE_1             81
-#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 131
+#define PRECALL_NO_KW_LIST_APPEND        73
+#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O  76
+#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS  77
+#define PRECALL_NO_KW_STR_1              78
+#define PRECALL_NO_KW_TUPLE_1            79
+#define PRECALL_NO_KW_TYPE_1             80
+#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST  81
 #define PRECALL_BOUND_METHOD            140
 #define PRECALL_PYFUNC                  141
 #define RESUME_QUICK                    143
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 9d36bc27c44d4..529ca5a295178 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -392,6 +392,7 @@ def _write_atomic(path, data, mode=0o666):
 #     Python 3.11a5 3483 (Use inline caching for COMPARE_OP and BINARY_SUBSCR)
 #     Python 3.11a5 3484 (Use inline caching for LOAD_ATTR, LOAD_METHOD, and 
 #                         STORE_ATTR)
+#     Python 3.11a5 3485 (Add an oparg to GET_AWAITABLE)
 
 #     Python 3.12 will start with magic number 3500
 
@@ -406,7 +407,7 @@ def _write_atomic(path, data, mode=0o666):
 # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
 # in PC/launcher.c must also be updated.
 
-MAGIC_NUMBER = (3484).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3485).to_bytes(2, 'little') + b'\r\n'
 _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little')  # For import.c
 
 _PYCACHE = '__pycache__'
diff --git a/Lib/opcode.py b/Lib/opcode.py
index f6e2dec32e0f5..3675780839671 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -92,7 +92,6 @@ def jabs_op(name, op, entries=0):
 def_op('PRINT_EXPR', 70)
 def_op('LOAD_BUILD_CLASS', 71)
 
-def_op('GET_AWAITABLE', 73)
 def_op('LOAD_ASSERTION_ERROR', 74)
 def_op('RETURN_GENERATOR', 75)
 
@@ -153,7 +152,7 @@ def jabs_op(name, op, entries=0):
 jabs_op('POP_JUMP_IF_NOT_NONE', 128)
 jabs_op('POP_JUMP_IF_NONE', 129)
 def_op('RAISE_VARARGS', 130)    # Number of raise arguments (1, 2, or 3)
-
+def_op('GET_AWAITABLE', 131)
 def_op('MAKE_FUNCTION', 132)    # Flags
 def_op('BUILD_SLICE', 133)      # Number of items
 jabs_op('JUMP_NO_INTERRUPT', 134) # Target byte offset from beginning of code
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-03-12-36-15.bpo-46841.apPev2.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-03-12-36-15.bpo-46841.apPev2.rst
new file mode 100644
index 0000000000000..6a45e6e88241b
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-03-03-12-36-15.bpo-46841.apPev2.rst	
@@ -0,0 +1,2 @@
+Use an oparg to simplify the construction of helpful error messages in
+:opcode:`GET_AWAITABLE`.
diff --git a/Python/ceval.c b/Python/ceval.c
index 915ab9313a95a..67c8b46db2d63 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -95,7 +95,7 @@ static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg
 static int check_except_type_valid(PyThreadState *tstate, PyObject* right);
 static int check_except_star_type_valid(PyThreadState *tstate, PyObject* right);
 static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs);
-static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int);
+static void format_awaitable_error(PyThreadState *, PyTypeObject *, int);
 static int get_exception_handler(PyCodeObject *, int, int*, int*, int*);
 static _PyInterpreterFrame *
 _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
@@ -2505,13 +2505,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
             PyObject *iter = _PyCoro_GetAwaitableIter(iterable);
 
             if (iter == NULL) {
-                int opcode_at_minus_4 = 0;
-                if ((next_instr - first_instr) > 4) {
-                    opcode_at_minus_4 = _Py_OPCODE(next_instr[-4]);
-                }
-                format_awaitable_error(tstate, Py_TYPE(iterable),
-                                       opcode_at_minus_4,
-                                       _Py_OPCODE(next_instr[-2]));
+                format_awaitable_error(tstate, Py_TYPE(iterable), oparg);
             }
 
             Py_DECREF(iterable);
@@ -7638,16 +7632,16 @@ format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg)
 }
 
 static void
-format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevprevopcode, int prevopcode)
+format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int oparg)
 {
     if (type->tp_as_async == NULL || type->tp_as_async->am_await == NULL) {
-        if (prevopcode == BEFORE_ASYNC_WITH) {
+        if (oparg == 1) {
             _PyErr_Format(tstate, PyExc_TypeError,
                           "'async with' received an object from __aenter__ "
                           "that does not implement __await__: %.100s",
                           type->tp_name);
         }
-        else if (prevopcode == WITH_EXCEPT_START || (prevopcode == CALL && prevprevprevopcode == LOAD_CONST)) {
+        else if (oparg == 2) {
             _PyErr_Format(tstate, PyExc_TypeError,
                           "'async with' received an object from __aexit__ "
                           "that does not implement __await__: %.100s",
diff --git a/Python/compile.c b/Python/compile.c
index 14595d9b576f5..ac9ddbcd79d03 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1978,7 +1978,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
                 return 0;
             }
             if (info->fb_type == ASYNC_WITH) {
-                ADDOP(c, GET_AWAITABLE);
+                ADDOP_I(c, GET_AWAITABLE, 2);
                 ADDOP_LOAD_CONST(c, Py_None);
                 ADD_YIELD_FROM(c, 1);
             }
@@ -5353,7 +5353,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
     ADDOP_I(c, CALL, 0);
 
     if (is_async_generator && type != COMP_GENEXP) {
-        ADDOP(c, GET_AWAITABLE);
+        ADDOP_I(c, GET_AWAITABLE, 0);
         ADDOP_LOAD_CONST(c, Py_None);
         ADD_YIELD_FROM(c, 1);
     }
@@ -5485,7 +5485,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
     VISIT(c, expr, item->context_expr);
 
     ADDOP(c, BEFORE_ASYNC_WITH);
-    ADDOP(c, GET_AWAITABLE);
+    ADDOP_I(c, GET_AWAITABLE, 1);
     ADDOP_LOAD_CONST(c, Py_None);
     ADD_YIELD_FROM(c, 1);
 
@@ -5522,7 +5522,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
     SET_LOC(c, s);
     if(!compiler_call_exit_with_nones(c))
         return 0;
-    ADDOP(c, GET_AWAITABLE);
+    ADDOP_I(c, GET_AWAITABLE, 2);
     ADDOP_LOAD_CONST(c, Py_None);
     ADD_YIELD_FROM(c, 1);
 
@@ -5536,7 +5536,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
     ADDOP_JUMP(c, SETUP_CLEANUP, cleanup);
     ADDOP(c, PUSH_EXC_INFO);
     ADDOP(c, WITH_EXCEPT_START);
-    ADDOP(c, GET_AWAITABLE);
+    ADDOP_I(c, GET_AWAITABLE, 2);
     ADDOP_LOAD_CONST(c, Py_None);
     ADD_YIELD_FROM(c, 1);
     compiler_with_except_finish(c, cleanup);
@@ -5710,7 +5710,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
         }
 
         VISIT(c, expr, e->v.Await.value);
-        ADDOP(c, GET_AWAITABLE);
+        ADDOP_I(c, GET_AWAITABLE, 0);
         ADDOP_LOAD_CONST(c, Py_None);
         ADD_YIELD_FROM(c, 1);
         break;
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index 7be7b168a755d..2060793b4f1c8 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -72,15 +72,15 @@ static void *opcode_targets[256] = {
     &&TARGET_PRINT_EXPR,
     &&TARGET_LOAD_BUILD_CLASS,
     &&TARGET_PRECALL_NO_KW_ISINSTANCE,
-    &&TARGET_GET_AWAITABLE,
+    &&TARGET_PRECALL_NO_KW_LIST_APPEND,
     &&TARGET_LOAD_ASSERTION_ERROR,
     &&TARGET_RETURN_GENERATOR,
-    &&TARGET_PRECALL_NO_KW_LIST_APPEND,
     &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O,
     &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
     &&TARGET_PRECALL_NO_KW_STR_1,
     &&TARGET_PRECALL_NO_KW_TUPLE_1,
     &&TARGET_PRECALL_NO_KW_TYPE_1,
+    &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST,
     &&TARGET_LIST_TO_TUPLE,
     &&TARGET_RETURN_VALUE,
     &&TARGET_IMPORT_STAR,
@@ -130,7 +130,7 @@ static void *opcode_targets[256] = {
     &&TARGET_POP_JUMP_IF_NOT_NONE,
     &&TARGET_POP_JUMP_IF_NONE,
     &&TARGET_RAISE_VARARGS,
-    &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST,
+    &&TARGET_GET_AWAITABLE,
     &&TARGET_MAKE_FUNCTION,
     &&TARGET_BUILD_SLICE,
     &&TARGET_JUMP_NO_INTERRUPT,



More information about the Python-checkins mailing list