Observation
TensorType.shapeArg(CGNode node, int literalVn) at com.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/types/TensorType.java:468 declares throws IOException. Inspecting the body shows it does no I/O — it walks SSA instructions, reads symbol-table entries, and constructs Dimension records. No file reads, no network, no JEP/Jython invocation.
The unjustified throws IOException cascades to every caller, which then either re-declares the exception or wraps it as a RuntimeException:
PythonTensorAnalysisEngine.getShapeSourceCalls (line 786): catch (IOException e) { throw new RuntimeException("Error while processing shape source call: " + call, e); }
PythonTensorAnalysisEngine.getSetShapeCallsSyntactic (line 865, added in ponder-lab/ML#333): identical wrapper pattern.
- Other
handleShapeSourceOp / getShapeSourceCalls callers throughout the engine.
Surfaced during PR #333 review (Copilot question about why we wrap IOException into RuntimeException). The honest answer is "we wrap it because TensorType.shapeArg declares it, but shapeArg doesn't actually need to declare it."
Proposed Fix
- Audit
TensorType.shapeArg's body to confirm no path throws IOException (a quick read suggests none; verify with a follow-up grep for any internal call that might).
- Remove the
throws IOException clause.
- Remove the
try/catch (IOException e) { throw new RuntimeException(...); } wrappers at every caller.
If any path inside shapeArg does throw something unchecked, switch to that exception type at the source rather than masking it as IOException.
Related
- ponder-lab/ML#333 — added a new caller that follows the legacy wrapper pattern; this issue tracks the cleanup of all callers in one pass.
Observation
TensorType.shapeArg(CGNode node, int literalVn)atcom.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/types/TensorType.java:468declaresthrows IOException. Inspecting the body shows it does no I/O — it walks SSA instructions, reads symbol-table entries, and constructsDimensionrecords. No file reads, no network, no JEP/Jython invocation.The unjustified
throws IOExceptioncascades to every caller, which then either re-declares the exception or wraps it as aRuntimeException:PythonTensorAnalysisEngine.getShapeSourceCalls(line 786):catch (IOException e) { throw new RuntimeException("Error while processing shape source call: " + call, e); }PythonTensorAnalysisEngine.getSetShapeCallsSyntactic(line 865, added in ponder-lab/ML#333): identical wrapper pattern.handleShapeSourceOp/getShapeSourceCallscallers throughout the engine.Surfaced during PR #333 review (Copilot question about why we wrap
IOExceptionintoRuntimeException). The honest answer is "we wrap it becauseTensorType.shapeArgdeclares it, butshapeArgdoesn't actually need to declare it."Proposed Fix
TensorType.shapeArg's body to confirm no path throwsIOException(a quick read suggests none; verify with a follow-up grep for any internal call that might).throws IOExceptionclause.try/catch (IOException e) { throw new RuntimeException(...); }wrappers at every caller.If any path inside
shapeArgdoes throw something unchecked, switch to that exception type at the source rather than masking it asIOException.Related