Annotate raise_qasm3_error as NoReturn - #416
Conversation
Argus reviewAuto-review is off for this repo. Tick the box below to run a review on this PR.
Estimated cost
Tip: you can also comment |
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Every path through raise_qasm3_error ends in a raise, but its `-> None`
annotation made each caller look like it could fall through. Eight
`# type: ignore[return]` comments and `inconsistent-return-statements`
suppressions existed only to silence that, and they hid real gaps:
- `_visit_switch_statement` returned `None` when no case matched and no
`default` was declared, so a valid switch crashed the caller with
`TypeError: 'NoneType' object is not iterable`.
- `qasm_variable_type_cast` fell off its branch chain instead of
reporting an unsupported target type.
- `validate_return_statement` fell off its void branch implicitly; it
now returns None explicitly, which also flattens the else arm.
Both crashes are fixed, and mypy and pylint now check those functions.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
573de7e to
46743da
Compare
Problem
raise_qasm3_erroralways raises — every path through it ends in araise. But it was annotated-> None, so tomypyandpylintevery caller looked like it could fall through and return nothing. Eight suppressions existed only to silence that:# type: ignore[return]onevaluate_expression,_visit_switch_statement,extract_qasm_version,map_qasm_op_to_callableinconsistent-return-statementsdisables invalidator.py,analyzer.py,maps/gates.py,maps/expressions.pyBlanket suppressions do not distinguish a function that provably raises from one that genuinely falls through, so real gaps were sitting behind them.
Change
raise_qasm3_erroris annotatedNoReturn, and all eight suppressions are removed.mypyandpylintthen found the three functions the annotation does not cover.A valid
switchcrashed._visit_switch_statementfell off its last branch when no case matched and nodefaultwas declared, returningNoneintoresult.extend(...):The spec does not require a
default, so this is valid and must simply contribute no statements. The redundantnot case_fulfilledguard is gone too — the loop returns as soon as a case matches, so reaching that line already means none did.qasm_variable_type_castfell off its branch chain rather than reporting an unsupported target type. It now raises aValidationErrornaming the type and variable.validate_return_statementfell off its void branch implicitly. It now returnsNoneexplicitly, which also lets theelsearm flatten out one level of nesting.Tests
test_switch_no_match_without_defaultcovers the crash. 803 passed, 3 skipped.Verified against CI's exact linters (
pylint==4.0.7,astroid==4.0.4): pylint exits 0 with no messages, isort and black exit 0, mypy reports only the pre-existingtabulatestub error.