Skip to content

Raise a validation error for stretch arithmetic instead of a TypeError - #417

Open
SAY-5 wants to merge 4 commits into
qBraid:mainfrom
SAY-5:fix-stretch-arithmetic-validationerror
Open

SAY-5 wants to merge 4 commits into
qBraid:mainfrom
SAY-5:fix-stretch-arithmetic-validationerror

Conversation

@SAY-5

@SAY-5 SAY-5 commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary of changes

Closes #389.

A duration initialized from arithmetic involving a stretch operand
(duration b = a + s;, 2 * s, a + 2 * s) raised a bare
TypeError: unsupported operand type(s) for +: 'float' and 'NoneType'. A stretch
carries no value until schedule time, so _check_var_initialized deliberately lets
it stay None; that None then reached qasm3_expression_op_map in
evaluate_expression and blew up in Python arithmetic. A bare stretch s; and
delay[s] q[0]; were unaffected, so the gap was confined to arithmetic.

Full symbolic stretch arithmetic is a larger piece of work, so this takes the
minimum acceptable path from the issue: when a binary expression has a None
operand that traces back to a stretch variable, raise a ValidationError naming
the variable and its span instead of letting the TypeError escape. Non-stretch
None operands fall through unchanged, and pure duration arithmetic is untouched.

Verified locally

tests/qasm3/declarations/test_classical.py passes, including two new cases under
test_stretch_arithmetic_not_supported. test_delay.py and test_box.py pass as
well. black, isort, pylint and mypy are clean on the touched files.

@SAY-5
SAY-5 requested a review from TheGupta2012 as a code owner August 26, 2026 07:09
@argus-eye

argus-eye Bot commented Aug 26, 2026

Copy link
Copy Markdown

Argus review

Auto-review is off for this repo. Tick the box below to run a review on this PR.

  • Trigger Argus review

Estimated cost

  • Files changed: 2
  • Diff lines (±): 78
  • Historical avg: ~243.6k tokens · ~$0.95 · across last 10 review(s)

Tip: you can also comment @argus-eye review at any time.

@coderabbitai

coderabbitai Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: qBraid/pyqasm
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: f7bbdee
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cd6a67c8-33a0-493e-916f-899f3e2dff5c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

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.

Share

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.

@SAY-5
SAY-5 force-pushed the fix-stretch-arithmetic-validationerror branch from 5abfdca to 17495c7 Compare October 25, 2026 09:25
@codecov-commenter

codecov-commenter commented Oct 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Comment thread src/pyqasm/expressions.py Outdated
return (None, [])

statements.extend(rhs_statements)
if lhs_value is None or rhs_value is None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that these values are None only in the case of stretch operands? What if they are None in some other operation and we raise this arithmetic stretch operand error?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not only stretch: 1 + 2 * f(3) with an extern f and 1 + g() with a subroutine that returns nothing also reach that line with a None operand (both still give the same TypeError as on main). The check no longer looks at lhs_value/rhs_value, it only fires when an operand is an identifier declared as stretch in scope whose value is still None, so those cases fall through untouched. The None part is still needed because const stretch s = 100ns; has a value and a + 2 * s evaluates fine with it on main, which test_const_stretch_arithmetic now covers.

Comment thread src/pyqasm/expressions.py Outdated
return var_value

@classmethod
def _find_stretch_operand(cls, expression):

@TheGupta2012 TheGupta2012 Oct 26, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be easier to just check the scope manager for the variable rather than recursively going into the expression again. We already register stretch declarations in the visitor-

self._scope_manager.add_var_in_scope(variable)

You can just do a ref check AND type check with _check_var_type

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed in 5581df0: _find_stretch_operand is gone, and the binary branch now looks up each Identifier operand with get_from_visible_scope and checks it with Qasm3Validator.validate_variable_type(var, StretchType), the same check _check_var_type runs (calling _check_var_type directly would raise on the non-stretch operand instead). Nested cases like a + 2 * s are still caught when the inner 2 * s is evaluated, so I added that one to the test. I also rebased on main to clear the CHANGELOG conflict.

@TheGupta2012 TheGupta2012 left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SAY-5 thanks for working on this ! Apologies for the delay in reviewing.

The idea is correct, but I think it'll be better to re-use the existing methods rather than adding a special handler for stretch name parsing

SAY-5 added 3 commits October 28, 2026 09:26
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
@SAY-5
SAY-5 force-pushed the fix-stretch-arithmetic-validationerror branch from 17495c7 to 5581df0 Compare October 28, 2026 16:41
Comment thread src/pyqasm/expressions.py
assert cls.visitor_obj
var = cls.visitor_obj._scope_manager.get_from_visible_scope(operand.name)
# const stretch declarations carry a value, so only reject unresolved ones
if Qasm3Validator.validate_variable_type(var, StretchType) and var.value is None:

@TheGupta2012 TheGupta2012 Nov 3, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should've caught this already but I'm only realizing it now - can we rather just update the _check_var_initialized method?

It already has a branch for the stretch type, so we can add this change there. I think this will be even cleaner than adding this single stretch type handling in the BinaryExpression branch

@TheGupta2012 TheGupta2012 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @SAY-5 thanks for the change! Your update makes me see a further simplification, can you please address it? It should be good to merge post that

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

stretch operands in duration arithmetic raise TypeError: ... 'float' and 'NoneType'

3 participants