Skip to content

Commit 2208869

Browse files
gramalingamCopilot
andcommitted
Generate placeholder graph inputs for None optional inputs
When _split_optional_inputs encounters a None entry, it now creates an untyped ir.Value placeholder (named input_N) and adds it to graph_inputs. This ensures the function signature declares all formal parameters, including absent optional ones, while the trace function still receives None so it can branch with 'if x is None:'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: G Ramalingam <grama@microsoft.com>
1 parent 72718bb commit 2208869

2 files changed

Lines changed: 24 additions & 13 deletions

File tree

onnxscript/_internal/builder.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -194,25 +194,34 @@ def _split_optional_inputs(
194194
) -> tuple[list[ir.Value | None], list[ir.Value]]:
195195
"""Split an input list into trace args and graph inputs.
196196
197+
For each ``None`` entry, a placeholder :class:`ir.Value` with a generated
198+
name (``input_0``, ``input_1``, …) is created and added to
199+
*graph_inputs* so that the function/graph signature declares the formal
200+
parameter. The corresponding *trace_args* entry remains ``None`` so that
201+
the trace function can branch with ``if x is None:``.
202+
197203
Returns:
198204
A tuple of (trace_args, graph_inputs) where trace_args preserves
199-
``None`` holes and graph_inputs contains only non-``None`` values.
205+
``None`` holes and graph_inputs includes placeholders for absent
206+
optional inputs.
200207
201208
Raises:
202209
ValueError: If any non-None input already has a producer or is
203210
already attached to a graph.
204211
"""
205212
trace_args: list[ir.Value | None] = list(inputs)
206213
graph_inputs: list[ir.Value] = []
207-
for v in trace_args:
214+
for i, v in enumerate(trace_args):
208215
if v is None:
209-
continue
210-
if v.producer() is not None:
211-
raise ValueError(
212-
f"Input {v.name!r} already has a producer node. "
213-
f"Pass freshly created ir.Value objects."
214-
)
215-
graph_inputs.append(v)
216+
# Placeholder: declared in function signature but unused in body.
217+
graph_inputs.append(ir.Value(name=f"input_{i}"))
218+
else:
219+
if v.producer() is not None:
220+
raise ValueError(
221+
f"Input {v.name!r} already has a producer node. "
222+
f"Pass freshly created ir.Value objects."
223+
)
224+
graph_inputs.append(v)
216225
return trace_args, graph_inputs
217226

218227

onnxscript/_internal/builder_test.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,7 +1750,7 @@ def test_build_function_lifts_initializers(self):
17501750
self.assertGreater(len(const_nodes), 0)
17511751

17521752
def test_build_function_optional_inputs_none(self):
1753-
"""build_function passes None for absent optional inputs."""
1753+
"""build_function passes None for absent optional inputs but declares them."""
17541754

17551755
def body(op, x, y, z):
17561756
self.assertIsNotNone(x)
@@ -1764,10 +1764,12 @@ def body(op, x, y, z):
17641764
domain="com.test",
17651765
name="OptionalInputs",
17661766
)
1767-
# Graph should have only 2 inputs (x and z), not 3
1768-
self.assertEqual(len(fn.graph.inputs), 2)
1767+
# Graph has 3 inputs: x, a placeholder for the absent y, and z
1768+
self.assertEqual(len(fn.graph.inputs), 3)
17691769
self.assertEqual(fn.graph.inputs[0].name, "x")
1770-
self.assertEqual(fn.graph.inputs[1].name, "z")
1770+
self.assertEqual(fn.graph.inputs[1].name, "input_1") # placeholder
1771+
self.assertIsNone(fn.graph.inputs[1].type) # untyped
1772+
self.assertEqual(fn.graph.inputs[2].name, "z")
17711773

17721774
def test_build_function_trace_appends_outputs(self):
17731775
"""build_function supports trace functions that append outputs directly."""

0 commit comments

Comments
 (0)