Repository navigation
Rewriter: guard string target and reference attributes in cast_constant_of_shape - #3145
Hardik K (hardikkaurani) wants to merge 7 commits into
Conversation
|
Hi Ti-Tai Wang (@titaiwangms), Could you please review this PR when you have a moment? It adds condition checks to |
| def check_cast_constant_of_shape_without_value(context, shape, dtype, **_) -> bool: | ||
| del context, shape | ||
| if dtype.is_ref(): |
There was a problem hiding this comment.
Addressed in the latest commits. Added _allow_other_attributes=False to op.ConstantOfShape(shape, _allow_other_attributes=False) in the no-value target pattern so that nodes with explicit value attributes do not match the fallback. Also added test_cast_after_constant_of_shape_with_ref_attr_is_not_fused using the full rule set to ensure reference attribute @fill is preserved without being overwritten with zero.
|
I recommend changes before merging: the new reference-value guard can fall through to the no-value rule and produce an incorrect zero-filled result. In this rewriter, patterns allow extra attributes by default. Consequently, Minimal fix: use The STRING guard itself is correct: ConstantOfShape does not support STRING outputs, regardless of whether serialization supports string tensors. The use of IR attribute/type/size checks is reasonable; Validation: static review of the diff, pattern-matcher defaults, rule fallthrough/function traversal, and ONNX ConstantOfShape specification only; tests were not run locally because onnx_ir is unavailable in this environment. |
…matching explicit values Set _allow_other_attributes=False on ConstantOfShape in the no-value pattern so that ConstantOfShape nodes with explicit value attributes (such as reference attributes or non-scalar tensors rejected by the first rule) do not match the no-value fallback and get erroneously replaced with zero. Also use scalar.as_tensor() for explicit tensor access. Signed-off-by: Hardik Kaurani <hardikkaurani1@gmail.com>
…ion in cast_constant_of_shape Add a regression test using the full rewrite rule set verifying that a function containing ConstantOfShape with a reference attribute @fill and a concrete numeric Cast target is not fused and does not fall through to the no-value rule to be replaced with a zero-filled tensor. Signed-off-by: Hardik Kaurani <hardikkaurani1@gmail.com>
…ion and no-value fusion verification Add regression tests verifying that ConstantOfShape with a non-scalar value attribute (e.g. float[2]) followed by Cast is rejected and not matched by the no-value fallback, and verify numerical equivalence for legitimate no-value ConstantOfShape cast fusion. Signed-off-by: Hardik Kaurani <hardikkaurani1@gmail.com>
|
Hi Ti-Tai Wang (@titaiwangms), Thank you for the review and catching that fallback issue! I have updated the PR accordingly across three focused commits:
All 7 tests in |
Ti-Tai Wang (titaiwangms)
left a comment
There was a problem hiding this comment.
The explicit-value fallback issue is resolved by _allow_other_attributes=False, and the added reference-value regression test covers the previously unsafe path. The use of as_tensor() is also clearer. No blocking findings remain in my static review.
Please update the PR description to include the strict no-value pattern matching and the new reference-value/non-singleton regression tests. Please also clarify that STRING fusion is invalid because ConstantOfShape does not support STRING output, not only because of serialization behavior.
Approval is based on static review; local tests were not run. Please ensure the required CI checks pass before merging.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3145 +/- ##
==========================================
+ Coverage 73.29% 73.41% +0.12%
==========================================
Files 267 269 +2
Lines 33214 33662 +448
Branches 3183 3218 +35
==========================================
+ Hits 24344 24713 +369
- Misses 7801 7876 +75
- Partials 1069 1073 +4 ☔ View full report in Codecov by Harness. |
Head branch was pushed to by a user without write access
|
The original ConstantOfShape rewrite fix still looks good, but I do not recommend merging the latest revision (ea06132) with the newly added nightly workarounds as-is. My earlier approval covered commit 6c5329a, before these additional changes. Blocking CI issue: In tests/function_libs/torch_lib/ops_test_data.py, lines 510–519 and 614–623, the new addbmm/baddbmm xfail matchers do not restrict dtype. They also match working int32 and int64 samples, causing the expected-failure mechanism to fail those tests with “Test unexpectedly passed.” The latest Linux torch-nightly job shows exactly four such failures: addbmm and baddbmm, each for int32 and int64. The macOS and Windows torch-nightly jobs are also failing. Evidence: https://github.com/microsoft/onnxscript/actions/runs/42106844617/job/127538046524 (the run head SHA matches ea06132). Please preferably move these unrelated nightly workarounds into a separate PR so this PR remains focused on the ConstantOfShape fix. If they remain here, narrow the xfails to the exact dtypes and samples demonstrated to fail, and rerun the affected tests. Please do not replace them with broad skips. The description now covers the intended rewrite changes, but it contains control characters that corrupt occurrences of value, operator names, and test names. Please clean those up as well. Validation: reviewed the added commit and the latest CI failure logs; no local tests were run. |
…Shape STRING output docstrings Signed-off-by: Hardik Kaurani <hardikkaurani1@gmail.com>
|
Hi Ti-Tai Wang (@titaiwangms), Thank you for the guidance. I've updated the branch with commit (754c4f86888e0e2c492fdda317b2a46605901e32)](https://github.com/microsoft/onnxscript/commit/754c4f86888e0e2c492fdda317b2a46605901e32) to address all the feedback:
All code and test formatting checks pass cleanly via Ruff. Please let me know if any further adjustments are needed. Thank you! |

Summary
This PR adds comprehensive validation to the
_cast_constant_of_shaperewrite rules to prevent invalid or unsafeCastfusion intoConstantOfShape.Specifically:
STRINGandUNDEFINEDtarget data types. Under the ONNX specification,ConstantOfShapedoes not supportSTRINGoutput element types; preventing this fusion preserves model validity and prevents downstream serialization errors.dtype.is_ref()) and scalar fill values (scalar.is_ref()), ensuring unexpanded function attributes are preserved.scalar_tensor.size == 1) and not string tensors._allow_other_attributes=FalsesoConstantOfShapenodes carrying an explicitvalueattribute cannot match the fallback rule and be silently replaced with zero.ConstantOfShaperewrite fix.Problem
Previously,
cast_constant_of_shape_ruleandcast_constant_of_shape_without_value_rulelacked sufficient validation:STRINGorUNDEFINEDoutput tensor element types forConstantOfShape. Fusing aCasttargetingir.DataType.STRINGresults in an invalid ONNX model and causes serialization failures (SerdeError: Bitwidth not available for ONNX data type: STRING).@targetor@fillwithin ONNX functions) do not possess concrete values at rewrite time and cannot be evaluated statically.ConstantOfShapenode with an explicitvalueattribute that failed the primary rule's guards could fall through to the fallback rule, silently discarding its original fill value in favor of zero.Solution
check_cast_constant_of_shapeandcheck_cast_constant_of_shape_without_valueto rejectir.DataType.STRINGandir.DataType.UNDEFINED.size == 1and non-string dtype, usingscalar.as_tensor()for explicit tensor access.op.ConstantOfShape(shape, _allow_other_attributes=False).Tests
Added and updated regression tests in
onnxscript/rewriter/rules/common/_cast_constant_of_shape_test.py:test_cast_after_constant_of_shape_is_fused: Validates legitimate fusion with an explicit fill value.test_cast_after_constant_of_shape_without_value_is_fused: Validates legitimate fusion without an explicit fill value.test_cast_to_string_after_constant_of_shape_is_not_fused: Verifies thatSTRING-target fusion is rejected with an explicit fill value becauseConstantOfShapedoes not supportSTRINGoutputs.test_cast_to_string_after_constant_of_shape_without_value_is_not_fused: Verifies thatSTRING-target fusion is rejected without an explicit fill value becauseConstantOfShapedoes not supportSTRINGoutputs.test_cast_after_constant_of_shape_with_ref_attr_is_not_fused: Verifies that reference-valued fill attributes (@fill) are preserved.test_cast_with_ref_attr_to_after_constant_of_shape_is_not_fused: Verifies that reference-valued target dtype attributes (@target) are preserved with an explicit fill value.test_cast_with_ref_attr_to_after_constant_of_shape_without_value_is_not_fused: Verifies that reference-valued target dtype attributes (@target) are preserved without an explicit fill value.test_cast_to_undefined_after_constant_of_shape_is_not_fused: Verifies thatUNDEFINED-target fusion is rejected with an explicit fill value.test_cast_to_undefined_after_constant_of_shape_without_value_is_not_fused: Verifies thatUNDEFINED-target fusion is rejected without an explicit fill value.test_cast_after_constant_of_shape_with_non_scalar_value_is_not_fused: Verifies that non-scalar fill tensors (float[2]) are rejected.test_cast_after_constant_of_shape_with_string_value_is_not_fused: Verifies that string-valuedConstantOfShapefill tensors are rejected.test_cast_after_constant_of_shape_without_value_numerical_correctness: Verifies numerical equivalence for legitimate no-value fusion.