Skip to content

bpo-45711: Remove type and traceback from exc_info #30122

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Dec 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,15 @@ the original TOS1.
.. opcode:: END_ASYNC_FOR

Terminates an :keyword:`async for` loop. Handles an exception raised
when awaiting a next item. If TOS is :exc:`StopAsyncIteration` pop 7
when awaiting a next item. If TOS is :exc:`StopAsyncIteration` pop 3
values from the stack and restore the exception state using the second
three of them. Otherwise re-raise the exception using the three values
of them. Otherwise re-raise the exception using the value
from the stack. An exception handler block is removed from the block stack.

.. versionadded:: 3.8

.. versionchanged:: 3.11
Exception representation on the stack now consist of one, not three, items.

.. opcode:: BEFORE_ASYNC_WITH

Expand Down Expand Up @@ -561,8 +563,10 @@ iterations of the loop.

.. opcode:: POP_EXCEPT

Pops three values from the stack, which are used to restore the exception state.
Pops a value from the stack, which is used to restore the exception state.

.. versionchanged:: 3.11
Exception representation on the stack now consist of one, not three, items.

.. opcode:: RERAISE

Expand All @@ -572,27 +576,32 @@ iterations of the loop.

.. versionadded:: 3.9

.. versionchanged:: 3.11
Exception representation on the stack now consist of one, not three, items.

.. opcode:: PUSH_EXC_INFO

Pops the three values from the stack. Pushes the current exception to the top of the stack.
Pushes the three values originally popped back to the stack.
Pops a value from the stack. Pushes the current exception to the top of the stack.
Pushes the value originally popped back to the stack.
Used in exception handlers.

.. versionadded:: 3.11


.. opcode:: WITH_EXCEPT_START

Calls the function in position 8 on the stack with the top three
items on the stack as arguments.
Calls the function in position 4 on the stack with arguments (type, val, tb)
representing the exception at the top of the stack.
Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception
has occurred in a :keyword:`with` statement.

.. versionadded:: 3.9
.. versionchanged:: 3.11
The ``__exit__`` function is in position 8 of the stack rather than 7.

.. versionchanged:: 3.11
The ``__exit__`` function is in position 4 of the stack rather than 7.
Exception representation on the stack now consist of one, not three, items.

.. opcode:: POP_EXCEPT_AND_RERAISE

Expand Down Expand Up @@ -890,10 +899,9 @@ All of the following opcodes use their arguments.
Performs exception matching for ``except*``. Applies ``split(TOS)`` on
the exception group representing TOS1. Jumps if no match is found.

Pops one item from the stack. If a match was found, pops the 3 items representing
the exception and pushes the 3 items representing the non-matching part of
the exception group, followed by the 3 items representing the matching part.
In other words, in case of a match it pops 4 items and pushes 6.
Pops one item from the stack (the match type). If a match was found,
next item (the exception) and pushes the non-matching part of the
exception group followed by the matching part.

.. versionadded:: 3.11

Expand All @@ -903,8 +911,8 @@ All of the following opcodes use their arguments.
Combines the raised and reraised exceptions list from TOS, into an exception
group to propagate from a try-except* block. Uses the original exception
group from TOS1 to reconstruct the structure of reraised exceptions. Pops
two items from the stack and pushes a triplet representing the exception to
reraise or three ``None`` if there isn't one.
two items from the stack and pushes 0 (for lasti, which is unused) followed
by the exception to reraise or ``None`` if there isn't one.

.. versionadded:: 3.11

Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ Other CPython Implementation Changes
reflected in the re-raised exception.
(Contributed by Irit Katriel in :issue:`45711`.)

* The interpreter state's representation of handled exceptions (a.k.a exc_info, or
_PyErr_StackItem) now has only the ``exc_value`` field, ``exc_type`` and ``exc_traceback``
have been removed as their values can be derived from ``exc_value``.
(Contributed by Irit Katriel in :issue:`45711`.)

New Modules
===========

Expand Down
2 changes: 1 addition & 1 deletion Include/cpython/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ typedef struct _err_stackitem {
* This ensures that the exception state is not impacted by "yields"
* from an except handler.
*/
PyObject *exc_type, *exc_value, *exc_traceback;
PyObject *exc_value;

struct _err_stackitem *previous_item;

Expand Down
12 changes: 2 additions & 10 deletions Include/internal/pycore_pyerrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,7 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)

static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state)
{
PyObject *t, *v, *tb;
t = exc_state->exc_type;
v = exc_state->exc_value;
tb = exc_state->exc_traceback;
exc_state->exc_type = NULL;
exc_state->exc_value = NULL;
exc_state->exc_traceback = NULL;
Py_XDECREF(t);
Py_XDECREF(v);
Py_XDECREF(tb);
Py_CLEAR(exc_state->exc_value);
}

PyAPI_FUNC(PyObject*) _PyErr_StackItemToExcInfoTuple(
Expand Down Expand Up @@ -114,6 +105,7 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(

#define _Py_FatalRefcountError(message) _Py_FatalRefcountErrorFunc(__func__, message)


#ifdef __cplusplus
}
#endif
Expand Down
5 changes: 3 additions & 2 deletions Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,10 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into
# BINARY_OP)
# Python 3.11a3 3465 (Add COPY_FREE_VARS opcode)
# Python 3.11a3 3466 (bpo-45292: PEP-654 except*)
# Python 3.11a4 3466 (bpo-45292: PEP-654 except*)
# Python 3.11a4 3467 (Change CALL_xxx opcodes)
# Python 3.11a4 3468 (Add SEND opcode)
# Python 3.11a4 3469 (bpo-45711: remove type, traceback from exc_info)

#
# MAGIC must change whenever the bytecode emitted by the compiler may no
Expand All @@ -383,7 +384,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 = (3468).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3469).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c

_PYCACHE = '__pycache__'
Expand Down
Loading