Skip to content

Commit 3fdc9e7

Browse files
Assert fix, tests are added
1 parent c4e7d24 commit 3fdc9e7

File tree

2 files changed

+32
-23
lines changed

2 files changed

+32
-23
lines changed

Lib/test/test_code.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,13 +449,21 @@ def spam5():
449449
if not value:
450450
return None
451451
...
452+
def spam_while1():
453+
while True:
454+
pass
455+
def spam_while2():
456+
while True:
457+
return None
452458
lambda1 = (lambda: None)
453459
for func in [
454460
spam1,
455461
spam2,
456462
spam3,
457463
spam4,
458464
spam5,
465+
spam_while1,
466+
spam_while2,
459467
lambda1,
460468
]:
461469
with self.subTest(func):
@@ -474,12 +482,24 @@ def spam9():
474482
if value:
475483
return True
476484
return None
485+
def spam_while3():
486+
i = 0
487+
while True:
488+
if i > 5:
489+
return i
490+
else:
491+
i += 1
492+
def spam_while4():
493+
while True:
494+
return True
477495
lambda2 = (lambda: True)
478496
for func in [
479497
spam6,
480498
spam7,
481499
spam8,
482500
spam9,
501+
spam_while3,
502+
spam_while4,
483503
lambda2,
484504
]:
485505
with self.subTest(func):

Objects/codeobject.c

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,10 +2097,6 @@ code_returns_only_none(PyCodeObject *co)
20972097
int len = (int)Py_SIZE(co);
20982098
assert(len > 0);
20992099

2100-
// The last instruction either returns or raises. We can take advantage
2101-
// of that for a quick exit.
2102-
_Py_CODEUNIT final = _Py_GetBaseCodeUnit(co, len-1);
2103-
21042100
// Look up None in co_consts.
21052101
Py_ssize_t nconsts = PyTuple_Size(co->co_consts);
21062102
int none_index = 0;
@@ -2113,29 +2109,22 @@ code_returns_only_none(PyCodeObject *co)
21132109
// None wasn't there, which means there was no implicit return,
21142110
// "return", or "return None".
21152111

2116-
// That means there must be
2117-
// an explicit return (non-None), or it only raises.
2112+
// The last instruction mostly either returns or raises.
2113+
// We can take advantage of that for a quick exit.
2114+
_Py_CODEUNIT final = _Py_GetBaseCodeUnit(co, len-1);
21182115
if (IS_RETURN_OPCODE(final.op.code)) {
21192116
// It was an explicit return (non-None).
21202117
return 0;
21212118
}
2122-
// It must end with a raise then. We still have to walk the
2123-
// bytecode to see if there's any explicit return (non-None).
2124-
assert(IS_RAISE_OPCODE(final.op.code));
2125-
for (int i = 0; i < len; i += _PyInstruction_GetLength(co, i)) {
2126-
_Py_CODEUNIT inst = _Py_GetBaseCodeUnit(co, i);
2127-
if (IS_RETURN_OPCODE(inst.op.code)) {
2128-
// We alraedy know it isn't returning None.
2129-
return 0;
2130-
}
2131-
}
2132-
// It must only raise.
2119+
2120+
none_index = -1;
21332121
}
2134-
else {
2135-
// Walk the bytecode, looking for RETURN_VALUE.
2136-
for (int i = 0; i < len; i += _PyInstruction_GetLength(co, i)) {
2137-
_Py_CODEUNIT inst = _Py_GetBaseCodeUnit(co, i);
2138-
if (IS_RETURN_OPCODE(inst.op.code)) {
2122+
2123+
// Walk the bytecode, looking for RETURN_VALUE.
2124+
for (int i = 0; i < len; i += _PyInstruction_GetLength(co, i)) {
2125+
_Py_CODEUNIT inst = _Py_GetBaseCodeUnit(co, i);
2126+
if (IS_RETURN_OPCODE(inst.op.code)) {
2127+
if (none_index >= 0) {
21392128
assert(i != 0);
21402129
// Ignore it if it returns None.
21412130
_Py_CODEUNIT prev = _Py_GetBaseCodeUnit(co, i-1);
@@ -2145,8 +2134,8 @@ code_returns_only_none(PyCodeObject *co)
21452134
continue;
21462135
}
21472136
}
2148-
return 0;
21492137
}
2138+
return 0;
21502139
}
21512140
}
21522141
return 1;

0 commit comments

Comments
 (0)