Skip to content

Commit 396b583

Browse files
authored
bpo-45711: Remove type and traceback from exc_info (GH-30122)
* Do not PUSH/POP traceback or type to the stack as part of exc_info * Remove exc_traceback and exc_type from _PyErr_StackItem * Add to what's new, because this change breaks things like Cython
1 parent 62a0a2a commit 396b583

File tree

14 files changed

+231
-392
lines changed

14 files changed

+231
-392
lines changed

Doc/library/dis.rst

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -474,13 +474,15 @@ the original TOS1.
474474
.. opcode:: END_ASYNC_FOR
475475

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

482482
.. versionadded:: 3.8
483483

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

485487
.. opcode:: BEFORE_ASYNC_WITH
486488

@@ -561,8 +563,10 @@ iterations of the loop.
561563

562564
.. opcode:: POP_EXCEPT
563565

564-
Pops three values from the stack, which are used to restore the exception state.
566+
Pops a value from the stack, which is used to restore the exception state.
565567

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

567571
.. opcode:: RERAISE
568572

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

573577
.. versionadded:: 3.9
574578

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

576582
.. opcode:: PUSH_EXC_INFO
577583

578-
Pops the three values from the stack. Pushes the current exception to the top of the stack.
579-
Pushes the three values originally popped back to the stack.
584+
Pops a value from the stack. Pushes the current exception to the top of the stack.
585+
Pushes the value originally popped back to the stack.
580586
Used in exception handlers.
581587

582588
.. versionadded:: 3.11
583589

584590

585591
.. opcode:: WITH_EXCEPT_START
586592

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

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

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

597606
.. opcode:: POP_EXCEPT_AND_RERAISE
598607

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

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

898906
.. versionadded:: 3.11
899907

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

909917
.. versionadded:: 3.11
910918

Doc/whatsnew/3.11.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ Other CPython Implementation Changes
195195
reflected in the re-raised exception.
196196
(Contributed by Irit Katriel in :issue:`45711`.)
197197

198+
* The interpreter state's representation of handled exceptions (a.k.a exc_info, or
199+
_PyErr_StackItem) now has only the ``exc_value`` field, ``exc_type`` and ``exc_traceback``
200+
have been removed as their values can be derived from ``exc_value``.
201+
(Contributed by Irit Katriel in :issue:`45711`.)
202+
198203
New Modules
199204
===========
200205

Include/cpython/pystate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ typedef struct _err_stackitem {
5656
* This ensures that the exception state is not impacted by "yields"
5757
* from an except handler.
5858
*/
59-
PyObject *exc_type, *exc_value, *exc_traceback;
59+
PyObject *exc_value;
6060

6161
struct _err_stackitem *previous_item;
6262

Include/internal/pycore_pyerrors.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,7 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)
2424

2525
static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state)
2626
{
27-
PyObject *t, *v, *tb;
28-
t = exc_state->exc_type;
29-
v = exc_state->exc_value;
30-
tb = exc_state->exc_traceback;
31-
exc_state->exc_type = NULL;
32-
exc_state->exc_value = NULL;
33-
exc_state->exc_traceback = NULL;
34-
Py_XDECREF(t);
35-
Py_XDECREF(v);
36-
Py_XDECREF(tb);
27+
Py_CLEAR(exc_state->exc_value);
3728
}
3829

3930
PyAPI_FUNC(PyObject*) _PyErr_StackItemToExcInfoTuple(
@@ -114,6 +105,7 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(
114105

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

108+
117109
#ifdef __cplusplus
118110
}
119111
#endif

Lib/importlib/_bootstrap_external.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,10 @@ def _write_atomic(path, data, mode=0o666):
371371
# Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into
372372
# BINARY_OP)
373373
# Python 3.11a3 3465 (Add COPY_FREE_VARS opcode)
374-
# Python 3.11a3 3466 (bpo-45292: PEP-654 except*)
374+
# Python 3.11a4 3466 (bpo-45292: PEP-654 except*)
375375
# Python 3.11a4 3467 (Change CALL_xxx opcodes)
376376
# Python 3.11a4 3468 (Add SEND opcode)
377+
# Python 3.11a4 3469 (bpo-45711: remove type, traceback from exc_info)
377378

378379
#
379380
# MAGIC must change whenever the bytecode emitted by the compiler may no
@@ -383,7 +384,7 @@ def _write_atomic(path, data, mode=0o666):
383384
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
384385
# in PC/launcher.c must also be updated.
385386

386-
MAGIC_NUMBER = (3468).to_bytes(2, 'little') + b'\r\n'
387+
MAGIC_NUMBER = (3469).to_bytes(2, 'little') + b'\r\n'
387388
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
388389

389390
_PYCACHE = '__pycache__'

0 commit comments

Comments
 (0)