Repository navigation
preserve runtime callable target functors - #3915
Draft
Ian Davis (idavis) wants to merge 1 commit into
Draft
Ian Davis (idavis) wants to merge 1 commit into
Ian Davis (idavis) wants to merge 1 commit into
Conversation
Ian Davis (idavis)
added this pull request to stack #3892
October 7, 2026 20:51
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes QIR and static-circuit generation when the requested entry is a runtime callable value with applied functors, such as:
Previously, runtime codegen could discard the callable value’s
AdjointorControlledstate and invoke the original body specialization. The branch carries functor information through both codegen backends, partial evaluation, specialization selection, argument resolution, validation, and diagnostics.The branch fixes runtime callable codegen bugs that could:
AdjointorControlledfrom a runtime callable value;1. Runtime adjoints invoking the body specialization
Compiling a runtime value representing
Adjoint Targetcould silently invokeTarget’s body.The generated program must fail with
adjoint selected. Successful execution would prove that codegen incorrectly invoked the empty body.The branch passes the runtime
FunctorAppinto partial evaluation and selects the adjoint specialization.2. Applied functors being lost on the direct reinvocation path
For ordinary concrete arguments, codegen may retain the original callable and invoke it directly during partial evaluation.
The expected rotation is
Rz(-0.25, q), notRz(0.25, q).The branch records the target functor alongside the callable ID and arguments when using the reinvocation backend.
3. Applied functors being lost on synthetic entries
When arguments contain callable values, codegen creates a synthetic FIR entry so defunctionalization can process them.
The synthetic entry must invoke
Adjoint Higher, notHigher.The branch wraps the synthetic callee with the runtime target’s functor applications.
4. Explicit adjoint and controlled specializations being ignored
Operations can provide behaviorally distinct specialization bodies.
Runtime requests for
Adjoint Target,Controlled Target, andControlled Adjoint Targetmust select their corresponding explicit specializations.The branch uses the runtime functor when resolving the specialization declaration.
5. Nested controlled arguments using the wrong input shape
Each controlled application adds another
(Qubit[], input)layer.The controlled specialization must receive all three controls and preserve the underlying
Unitinput.The branch tracks control depth, peels the correct number of tuple layers, and flattens the control arrays for invocation.
6. Nested controls changing explicit specialization gate order
A controlled-adjoint specialization can have an observable gate sequence.
Codegen must preserve:
X;X.The branch preserves both control depth and adjoint selection in QIR and static circuits.
7. Target and callable-argument functors interfering
A higher-order target and its callable argument can each have an independent adjoint application.
These runtime combinations have different results:
The branch preserves the target’s functor separately from functors already attached to callable-valued arguments.
8. Unsupported runtime functors reaching codegen
Runtime API values can request a functor that the callable does not support.
Invalid runtime requests include the equivalents of:
Valid Q# source rejects these expressions, but runtime clients can hold or construct callable values independently.
The branch validates the requested functor before codegen and reports
InvalidRuntimeCallableFunctorinstead of selecting a nonexistent specialization or panicking.9. Duplicate controls not being checked at the target invocation
Nested runtime controls can reuse a qubit across layers or as the target input.
The same qubit appears in both control layers.
The branch passes control depth and the callable’s source span into argument resolution, preserving the “qubits in invocation are not unique” diagnostic at
Target.10. Runtime-adjoint failures losing their source location
A failure in the selected specialization must remain attributed to the original Q# source.
QIR and static-circuit generation must report the failure at:
The branch invokes the actual adjoint specialization during partial evaluation and preserves its source span.