Commit d2b51bb
Summary:
For #1795
This implements [PEP 765](https://peps.python.org/pep-0765/) which disallows `return`, `break`, and `continue` statements that directly exit a `finally` block. Starting in Python
3.14, these statements emit a `SyntaxWarning` because they can silently mask exceptions.
## The Issue
When a `return`, `break`, or `continue` statement exits a `finally` block, any exception being propagated is silently discarded:
```python
def f():
try:
raise ValueError("important error")
finally:
return 42 # Silences the ValueError!
for x in range(10):
try:
raise ValueError()
finally:
break # Silences the ValueError!
```
However, these statements are valid when inside a nested function or nested loop within the finally block:
```python
def f():
try:
pass
finally:
def inner():
return 42 # OK: exits inner function, not finally
for x in range(5):
break # OK: exits inner loop, not finally
```
The Fix
I made several changes to detect these violations during the binding phase:
- Added InvalidReturnInFinally error kind in crates/pyrefly_config/src/error_kind.rs with Warn severity (matching Python's SyntaxWarning)
- Added finally_depth tracking in pyrefly/lib/binding/scope.rs:
- Added finally_depth: usize field to Scope struct
- This resets to 0 when entering a new function scope, so nested functions are correctly allowed
- Added enter_finally(), exit_finally(), and in_finally() methods to Scopes
- Added in_finally flag on loops in pyrefly/lib/binding/scope.rs:
- Added in_finally: bool field to Loop struct
- Records whether a loop was started inside a finally block
- Added loop_protects_from_finally_exit() method to check if break/continue targets a nested loop
- Added checks for return/break/continue in pyrefly/lib/binding/stmt.rs:
- Check in record_return() for return statements
- Check in Stmt::Break and Stmt::Continue handlers
- All checks are gated to Python 3.14+ via self.sys_info.version().at_least(3, 14)
- Added documentation in website/docs/error-kinds.mdx for invalid-return-in-finally
Pull Request resolved: #1798
Test Plan:
| Test | Description |
|------------------------------------------|--------------------------------|
| test_pep765_return_in_finally | return in finally → warning |
| test_pep765_break_in_finally | break in finally → warning |
| test_pep765_continue_in_finally | continue in finally → warning |
| test_pep765_return_in_nested_function_ok | return in nested function → OK |
| test_pep765_break_in_nested_loop_ok | break in nested loop → OK |
| test_pep765_continue_in_nested_loop_ok | continue in nested loop → OK |
| test_pep765_return_python313_no_error | no warning on Python 3.13 |
Verification:
Run PEP 765 tests
cargo test test_pep765
Result: 7 passed
Run all flow_branching tests
cargo test flow_branching
Result: 86 passed
Run all tests
cargo test
Result: 3057 passed
Fixes #1795
Reviewed By: grievejia
Differential Revision: D88746329
Pulled By: yangdanny97
fbshipit-source-id: f4690916e33e5fda99db83b5a61fae963e6c8328
1 parent 9223880 commit d2b51bb
3 files changed
+155
-4
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
886 | 886 | | |
887 | 887 | | |
888 | 888 | | |
| 889 | + | |
| 890 | + | |
889 | 891 | | |
890 | 892 | | |
891 | 893 | | |
892 | | - | |
| 894 | + | |
893 | 895 | | |
894 | 896 | | |
895 | 897 | | |
| 898 | + | |
896 | 899 | | |
897 | 900 | | |
898 | 901 | | |
| |||
956 | 959 | | |
957 | 960 | | |
958 | 961 | | |
| 962 | + | |
| 963 | + | |
959 | 964 | | |
960 | 965 | | |
961 | 966 | | |
| |||
970 | 975 | | |
971 | 976 | | |
972 | 977 | | |
| 978 | + | |
973 | 979 | | |
974 | 980 | | |
975 | 981 | | |
| |||
1139 | 1145 | | |
1140 | 1146 | | |
1141 | 1147 | | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
1142 | 1176 | | |
1143 | 1177 | | |
1144 | 1178 | | |
| |||
2630 | 2664 | | |
2631 | 2665 | | |
2632 | 2666 | | |
| 2667 | + | |
2633 | 2668 | | |
2634 | 2669 | | |
2635 | 2670 | | |
2636 | 2671 | | |
2637 | 2672 | | |
2638 | | - | |
| 2673 | + | |
| 2674 | + | |
| 2675 | + | |
| 2676 | + | |
2639 | 2677 | | |
2640 | 2678 | | |
2641 | 2679 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
272 | 272 | | |
273 | 273 | | |
274 | 274 | | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
275 | 283 | | |
276 | 284 | | |
277 | 285 | | |
| |||
864 | 872 | | |
865 | 873 | | |
866 | 874 | | |
| 875 | + | |
867 | 876 | | |
| 877 | + | |
868 | 878 | | |
869 | 879 | | |
870 | 880 | | |
| |||
984 | 994 | | |
985 | 995 | | |
986 | 996 | | |
987 | | - | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
988 | 1009 | | |
989 | 1010 | | |
990 | | - | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
991 | 1023 | | |
992 | 1024 | | |
993 | 1025 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
8 | 10 | | |
9 | 11 | | |
10 | 12 | | |
| |||
1321 | 1323 | | |
1322 | 1324 | | |
1323 | 1325 | | |
| 1326 | + | |
| 1327 | + | |
| 1328 | + | |
| 1329 | + | |
| 1330 | + | |
| 1331 | + | |
| 1332 | + | |
| 1333 | + | |
| 1334 | + | |
| 1335 | + | |
| 1336 | + | |
| 1337 | + | |
| 1338 | + | |
| 1339 | + | |
| 1340 | + | |
| 1341 | + | |
| 1342 | + | |
| 1343 | + | |
| 1344 | + | |
| 1345 | + | |
| 1346 | + | |
| 1347 | + | |
| 1348 | + | |
| 1349 | + | |
| 1350 | + | |
| 1351 | + | |
| 1352 | + | |
| 1353 | + | |
| 1354 | + | |
| 1355 | + | |
| 1356 | + | |
| 1357 | + | |
| 1358 | + | |
| 1359 | + | |
| 1360 | + | |
| 1361 | + | |
| 1362 | + | |
| 1363 | + | |
| 1364 | + | |
| 1365 | + | |
| 1366 | + | |
| 1367 | + | |
| 1368 | + | |
| 1369 | + | |
| 1370 | + | |
| 1371 | + | |
| 1372 | + | |
| 1373 | + | |
| 1374 | + | |
| 1375 | + | |
| 1376 | + | |
| 1377 | + | |
| 1378 | + | |
| 1379 | + | |
| 1380 | + | |
| 1381 | + | |
| 1382 | + | |
| 1383 | + | |
| 1384 | + | |
| 1385 | + | |
| 1386 | + | |
| 1387 | + | |
| 1388 | + | |
| 1389 | + | |
| 1390 | + | |
| 1391 | + | |
| 1392 | + | |
| 1393 | + | |
| 1394 | + | |
| 1395 | + | |
| 1396 | + | |
| 1397 | + | |
| 1398 | + | |
| 1399 | + | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + | |
| 1404 | + | |
0 commit comments