Quantum Intermediate Representation (QIR) is a program representation based on LLVM IR. The [specification](https://github.com/qir-alliance/qir-spec) is developed by the QIR Alliance. QIR specifies different [profiles](https://github.com/qir-alliance/qir-spec/blob/main/specification/v0.1/7_Profiles.md) for different hardware capabilities. The Q# compiler can generate QIR that is compatible with the [Base Profile](https://github.com/qir-alliance/qir-spec/blob/main/specification/under_development/profiles/Base_Profile.md), which is limited to programs that can be represented as a sequence of operations. The compiler can also generate QIR that is compatible with the [Adaptive Profile](https://github.com/qir-alliance/qir-spec/blob/main/specification/under_development/profiles/Adaptive_Profile.md). The 'Adaptive_RI' profile allows additional capabilities such as mid-circuit measurement, branching based on measurement results or performing classical integer computations at runtime, and gets its name from the adaptive profile and two extensions: qubit reset support and integer computation. Q# code that runs in the local simulator is not limited to any subset of QIR described in a 'profile'. We refer to this as `Unrestricted`. When developing Q# code, you can set the target profile via either the "Set the Azure Quantum QIR target profile" command (as shown below) or clicking on the editor status bar which will display the current target profile (either "QIR base", "Unrestricted" or "QIR Adaptive RI" if the experimental settings are enabled). image If the current program is not compatible with the selected target profile, you will get errors in the editor when targeting "QIR Base" or "QIR Adaptive RI". If the program is compatible, you can view the generated QIR via the "Get QIR for the current Q# program" menu item (also shown in the clipping above). The following sections describe errors that can be encountered when compiling Q# with a specific profile, along with examples and possible mitigations. These errors come from the Runtime Capabilities Check pass that validates the capabilities used by the program are compatible with the capabilities of the configured target profile. ## Runtime Capabilities Check Errors ### Use of Dynamic Bool Code: `Qsc.CapabilitiesCk.UseOfDynamicBool` This indicates the program is using Boolean values that depend on qubit measurement when the configured target profile does not support Boolean variables. This usually occurs when compiling against the Base Profile, which does not allow for any branching based on measurement results. For example, the following code uses a dynamic bool to apply a gate operation to a qubit: ```qsharp use q = Qubit(); H(q); if M(q) == One { X(q); } ``` The comparison of a measurement result to the literals `One`, `Zero`, or to another measurement result cannot be included in a program compiled for a target without support for Boolean variables. ### Use of Dynamic Integer Code: `Qsc.CapabilitiesCk.UseOfDynamicInt` This indicates the program is using integer values that depend on qubit measurement when the configured target profile does not support integer variables. This can happen when compiling against target profiles that do not support the Adaptive Profile with the integer computation extension. For example, the following code calculates a dynamic integer: ```qsharp mutable x = 0; use qs = Qubit[3]; for q in qs { H(q); if M(q) == One { set x += 1; } } ``` The use of integer computation that depends on measurement results cannot be included in a program compiled for a target profile that does not support integer variables and computation. ### Use of Dynamic Pauli Code: `Qsc.CapabilitiesCk.UseOfDynamicPauli` This indicates the program is using a `Pauli` value that depends on qubit measurement when the configured target profile does not support `Pauli` variables. Which of the literal values `PauliX`, `PauliY`, `PauliZ` and `PauliI` a variable holds must be known at compile time to be considered static. For example, the following code uses a dynamic `Pauli` value: ```qsharp use q = Qubit(); let p = if M(q) == One { PauliX } else { PauliI }; R(p, 3.14, q); ``` The use of `Pauli` variables whose value depends on a measurement result cannot be included in a program compiled for a target profile that does not support `Pauli` variables. ### Use of Dynamic Range Code: `Qsc.CapabilitiesCk.UseOfDynamicRange` This indicates the program is using a `Range` value that depends on qubit measurement when the configured target profile does not support `Range` variables. A `Range` can be considered dynamic if either it uses a dynamic integer for one of the elements: ```qsharp use q = Qubit(); let end = if M(q) == One { 1 } else { 2 }; let range = 0..end; ``` or if the choice between two static ranges is based on a dynamic value like a measurement result: ```qsharp use q = Qubit(); let range = if M(q) == One { 0..1 } else { 0..2 }; ``` The use of `Range` variables whose value depends on a measurement result cannot be included in a program compiled for a target profile that does not support `Range` variables. ### Use of Dynamic Double Code: `Qsc.CapabilitiesCk.UseOfDynamicDouble` This indicates the program is using floating point values that depend on qubit measurement when the configured target profile does not support floating point variables. This can happen when compiling against target profiles that do not support the Adaptive Profile with the floating point computation extension. For example, the following code calculates a dynamic `Double`: ```qsharp mutable x = 0.0; use qs = Qubit[3]; for q in qs { H(q); if M(q) == One { set x += 1.0; } } ``` The use of floating point computation that depends on measurement results cannot be included in a program compiled for a target profile that does not support floating point variables and computation. ### Use of Dynamic Qubit Code: `Qsc.CapabilitiesCk.UseOfDynamicQubit` This indicates the program is using a qubit whose identifier depends on a qubit measurement when the configured target profile does not support dyanmic qubit addressing. Most targets require static qubit identifiers, where the each qubit used is statically known at compile time. A qubit variable set based on a measurement result cannot be statically identified at each point of the program, such as this example: ```qsharp use (q0, q1, q2) = (Qubit(), Qubit(), Qubit()); let chosen_q = if M(q0) == One { q1 } else { q2 }; ``` The use of dynamic qubit identifiers cannot be included in a program compiled for a target profile that only supports static qubit identifiers. ### Use of Dynamic Result Code: `Qsc.CapabilitiesCk.UseOfDynamicResult` This indicates the program is using a result whose identifier depends on a qubit measurement when the configured target profile does not support dyanmic result addressing. Most targets require static result identifiers, where the each result value used is statically known at compile time. A result variable conditionally updated based on a measurement result cannot be statically identified at each point of the program, such as this example: ```qsharp use q = Qubit(); mutable res = M(q); if res == One { set res = M(q); } ``` The use of dynamic result identifiers cannot be included in a program compiled for a target profile that only supports static result identifiers. If the configured target profile supports dynamic Boolean or integer values, try using those instead. For example: ```qsharp use q = Qubit(); mutable res = M(q) == One; if res { set res = M(q) == One; } ``` ### Use of Dynamic Tuple Code: `Qsc.CapabilitiesCk.UseOfDynamicTuple` This indicates the program is using a tuple value that depends on a qubit measurement when the configured target profile does not support tuple variables. For example, the following code uses a dynamic tuple: ```qsharp use q = Qubit(); let tuple = if M(q) == One { (1, false) } else { (2, true) }; ``` The use of dynamic tuple values cannot be included in a program compiled for a target profile that does not support tuple variables. ### Use of Dynamic Big Integer Code: `Qsc.CapabilitiesCk.UseOfDynamicBigInt` This indicates the program is using `BigInt` values that depend on qubit measurement when the configured target profile does not support `BigInt` variables. For example, the following code calculates a dynamic `BigInt`: ```qsharp mutable x = 0L; use qs = Qubit[3]; for q in qs { H(q); if M(q) == One { set x += 1L; } } ``` The use of `BigInt` computation that depends on measurement results cannot be included in a program compiled for a target profile that does not support `BigInt` variables and computation. ### Use of Dynamic String Code: `Qsc.CapabilitiesCk.UseOfDynamicString` This indicates the program is using a string value that depends on qubit measurement when the configured target profile does not support string variables. A dynamic string could come from a choice between static strings that depends on a dynamic variable: ```qsharp use q = Qubit(); let str = if M(q) == One { "One" } else { "Zero" }; ``` or it can come from an interpolated string where dynamic values are evaluated into the resulting string: ```qsharp use q = Qubit(); let val = if M(q) == One { 1 } else { 0 }; let str = $"Measured: {val}"; ``` The use of strings whose value depends on measurement results cannot be included in a program compiled for a target profile that does not support string variables. ### Use of Dynamic Exponent Code: `Qsc.CapabilitiesCk.UseOfDynamicExponent` This indicates the program requires an exponentiation where the exponent or power is depends on a measurement result when the configured target profile does not support backward branching or loops. This typically occurs when the target does not support the Adaptive Profile with the backward branching extension. When the right-hand side of the exponent operator `^` is statically known at compile time and the left-hand side is a supported dynamic variable type, the exponentiation can be reduced to a fixed number of multiplications. A dynamic right-hand side cannot be reduced this way, as in this example: ```qsharp use q = Qubit(); let pow = if M(q) == One { 2 } else { 3 }; let val = 2 ^ pow; ``` The use of exponents whose value depends on measurement results cannot be included in a program compiled for a target profile that does not support backward branching. ### Use of Dynamically-Sized Array Code: `Qsc.CapabilitiesCk.UseOfDynamicallSizedArray` This indicates the program uses an array whose size or contents at specific indices depend on a measurement result when the configured target profile does not support array variables. For targets without array support, array variables are eliminated by compilation to produce distinct values for each array index. If the size or values at each index of the array cannot be statically determined at compile time the program requires the use of an array variable. For example, the follow code uses an array whose size is dependent on a measurement result: ```qsharp use q = Qubit(); mutable arr = [1, 2]; if M(q) == One { set arr += [3]; } ``` In some cases, even if the size of the array stays the same but an expression conditioned on a measurement changes the value of one of the indices, the compiler can no longer statically determine which index corresponds to which value. For example: ```qsharp use q = Qubit(); mutable arr = [0, 0]; if M(q) == One { set arr w/= 0 <- 1; } ``` The use of arrays whose size or specific contents depend on a measurement result cannot be included in a program compiled for a target profile that does not support array variables. ### Use of Dynamic User-Defined Type Code: `Qsc.CapabilitiesCk.UseOfDynamicUdt` This indicates that the program uses a user-defined type or UDT whose contents depend on a measurement result when the configured target profile does not support struct variables. For targets without struct support, user-defined types are eliminated by compilation to produce distinct variables for each type field. If the contents of the fields cannot be statically determined at compile time the program requires the use of struct variables. For example, the follow code uses a UDT whose contents depend on a measurement result: ```qsharp newtype Pair = (Left : Int, Right : Int); use q = Qubit(); mutable pair = Pair(0, 0); if M(q) == One { set pair w/= Left <- 1; } ``` The use of UDTs whose specific contents depend on a measurement result cannot be included in a program compiled for a target profile that does not support struct variables. ### Use of Dynamic Function Code: `Qsc.CapabilitiesCk.UseOfDynamicArrowFunction` This indicates that the program uses a function variable whose value is dependent on a measurement result when the configured target profile does not support function variables. For targets without function variable support the specific function called in each call expression must be known at compile time. For example, the following code uses a function whose value depends on a measurement result: ```qsharp open Microsoft.Quantum.Math; use q = Qubit(); mutable f = Cos; if M(q) == One { set f = Sin; } ``` The use of function variables whose value depends on a measurement result cannot be included in a program compiled for a target profile that does not support function variables. ### Use of Dynamic Operation Code: `Qsc.CapabilitiesCk.UseOfDynamicArrowOperation` This indicates that the program uses an operation variable whose value is dependent on a measurement result when the configured target profile does not support operation variables. For targets without operation variable support the specific operation called in each call expression must be known at compile time. For example, the following code uses an operation whose value depends on a measurement result: ```qsharp use q = Qubit(); mutable op = I; if M(q) == One { set op = X; } ``` The use of operation variables whose value depends on a measurement result cannot be included in a program compiled for a target profile that does not support operation variables. ### Call to Cyclic Function with Dynamic Argument Code: `Qsc.CapabilitiesCk.CallToCyclicFunctionWithDynamicArg` This indicates that the program uses a call to a function that was detected as potentially cyclic with one or more arguments that depend on a measurement result when the configured target profile does not support multiple declared functions. When compiling for a target profile that does not support multiple declared functions, each invocation of a function needs to be inlined into the single entry point function provided to the target. A function that is part of a cycle and is passed an argument that is dynamic at runtime cannot be fully inlined and requires the use of a function definition that can be invoked at runtime. For example, the following code produces this error because it passes a dynamic value to a cyclic function: ```qsharp function CountDown(i : Int) : Int { if i <= 0 { return 0; } return CountDown(i - 1); } use q = Qubit(); let i = if M(q) == One { 2 } else { 1 }; CountDown(i); ``` If instead the cyclic function were given a static argument that does not depend on measurement results, the compiler can assume from that and the fact that Q# functions are pure functions (do not have side effects) that the recursive execution can be evaluated during code generation. For example, this code does not produce the error: ```qsharp function CountDown(i : Int) : Int { if i <= 0 { return 0; } return CountDown(i - 1); } use q = Qubit(); let i = 1; CountDown(i); ``` It is worth noting that this analysis does not guarantee that the recursion terminates; if a cyclic function is invoked with a value that causes an infinite recursiion QIR code generation can hang or run out of memory. The use of cyclic functions called with arguments that depend on measurement results cannot be included on in a program compiled for a target profile that does not support multiple declared functions. ### Cyclic Operation Definition Code: `Qsc.CapabilitiesCk.CyclicOperationSpec` This indicates that the program defines an operation with a specialization that includes a call cycle when compiling for a target profile that does not support operation variables. When this kind of cycle exists, compile time analysis cannot determine the properties of the operation and assumes it will need to be emitted as a dynamic dispatch in the QIR code generated. For example, this can happen when the body speciliazation calls into itself: ```qsharp operation CyclicBody() : Unit { CyclicBody(); } ``` The use of cyclic operation definitions cannot be included in a program compiled for a target profile that does not support operation variables. ### Call to Cyclic Operation Code: `Qsc.CapabilitiesCk.CallToCyclicOperation This indicates a program includes a call to an operation that has been defined with a call cycle when compiling for a target profile that does not support operation variables. This is distinct from the `Qsc.CapabilitiesCk.CyclicOperationSpec` since this is the error that appears at the call site rather than at the definition. For example, the following generates both errors because it both defines and calls a cyclic operation: ```qsharp operation CyclicBody() : Unit { CyclicBody(); } CyclicBody(); ``` The use of calls to an operation with a cyclic definition cannot be included in a program compiled for a target profile that does not support operation variables. ### Call to Dynamic Callee Code: `Qsc.CapabilitiesCk.CallToDynamicCallee` This indicates the program includes a call to a function or operation whose resolution depends on a measurement result when compiling for a target profile that does not support function or operation variables. This is distinct from both `Qsc.CapabilitiesCk.UseOfDynamicArrowFunction` and `Qsc.CapabilitiesCk.UseOfDynamicArrowOperation` since this is the error that appears at the call site rather than the declaration or update of a variable. For example, the following generates both errors because it both creates a dynamic callable varaible and calls it: ```qsharp open Microsoft.Quantum.Math; use q = Qubit(); let fn = M(q) == One ? Cos | Sin; fn(3.14); ``` The use of calls to functions or operations whose resolution depends on measurement result cannot be included in a program compiled for a target profile that does not support operation variables. ### Measurement Within a Dynamic Scope Code: `Qsc.CapabilitiesCk.MeasurementWithinDynamicScope` This indicates that the program includes a qubit measurement that may or may not occur dependent on a previous measurement when compiling for a target profile that does not support adaptive execution. This typically occurs when compiling for the Base Profile, which requires all measurements to be deferred to the end of execution and cannot support measurements that are not known to deterministically occur when analyzed at compile time. For example, the follow code will produce this error since it uses a measurement that can be skipped based on another measurement: ```qsharp use q = Qubit(); if M(q) == One { let r = M(q); } ``` The use of qubit measurements that depend on another measurement result cannot be included in a program compiled for a target profile that does not support adaptive execution. ### Call to Custom Measurement Code: `Qsc.CapabilitiesCk.CallToCustomMeasurement` This indicates that the program calls a custom measurement, which is not supported when compiling for a target profile that does not support adaptive execution. This typically occurs when compiling for the Base Profile. For example, the following code will produce this error if compiled for the Base Profile. ```qsharp operation Main() : Result { use q = Qubit(); Mx(q); } @Measurement() operation Mx(target: Qubit) : Result { body intrinsic; } ``` Calls to custom measurements cannot be included in a program compiled for a target profile that does not support adaptive execution. ### Call to Custom Reset Code: `Qsc.CapabilitiesCk.CallToCustomReset` This indicates that the program calls a custom reset, which is not supported when compiling for a target profile that does not support adaptive execution. This typically occurs when compiling for the Base Profile. For example, the following code will produce this error if compiled for the Base Profile. ```qsharp operation Main() : Unit { use q = Qubit(); MyReset(q); } @Reset() operation MyReset(target: Qubit) : Result { body intrinsic; } ``` Calls to custom resets cannot be included in a program compiled for a target profile that does not support adaptive execution. ### Use of Dynamic Array Index Code: `Qsc.CapabilitiesCk.UseOfDynamicIndex` This indicates that the program uses an index into an array that depends on a measurement result when compiling for a target profile that does not support array variables. For targets without array support, array variables are eliminated by compilation to produce distinct variables for each array index accessed. If the array index cannot be statically determined at compile time the program requires the use of an array variable. For example, the following program uses an array index that depends on a measurement result: ```qsharp use q = Qubit(); let arr = [5, 7]; let idx = if M(q) == One { 1 } else { 0 }; let val = arr[idx]; ``` The use of an integer that depends on a measurement result in an array index cannot be included in a program compiled for a target profile that does not support array variables. ### Return Within a Dynamic Scope Code: `Qsc.CapabilitiesCk.ReturnWithinDynamicScope` This indicates that the program uses a return from a function or operation that may be conditionally skipped based on a measurement result. For example, the following code performs an early return based on a measurement result: ```qsharp operation Main() : Result { use q = Qubit(); for _ in 1..10 { if M(q) == One { return One; } } return Zero; } ``` Instead, consider patterns like the use an update of a mutable variable or implicit returns, which avoid the control flow short-circuiting behavior of explict returns. ### Loop with Dynamic Condition Code: `Qsc.CapabilitiesCk.LoopWithDynamicCondition` This indicates that the program uses a loop whose termination condition depends on a measurement result when compiling for a target profile that does not support backward branching or loops. This typically occurs when compiling for the Adaptive Profile without the backward branching extension. When backward branching is not supported, each loop in the program must be statically unrolled into a repetition of instructions. A dynamic loop cannot be unrolled in this way and requires backward branching at runtime. For example, the following code uses a dynamic loop condition: ```qsharp use q = Qubit(); repeat { H(q); } until M(q) == One; ``` The use of loops with a termination condition that depends on a measurement result cannot be included in a program compiled for a target profile that does not support backward branching. ### Use of Bool Output Code: `Qsc.CapabilitiesCk.UseOfBoolOutput` This indicates that the program uses an entry callable or expression that has a `Bool` type as part of the output when compiling for a target profile that does not support Boolean variables. A type cannot be included in the output of a program unless the target profile includes support for variables of that type. ### Use of Double Output Code: `Qsc.CapabilitiesCk.UseOfDoubleOutput` This indicates that the program uses an entry callable or expression that has a `Double` type as part of the output when compiling for a target profile that does not support floating-point variables. A type cannot be included in the output of a program unless the target profile includes support for variables of that type. ### Use of Integer Output Code: `Qsc.CapabilitiesCk.UseOfIntOutput` This indicates that the program uses an entry callable or expression that has an `Int` type as part of the output when compiling for a target profile that does not support integer variables. A type cannot be included in the output of a program unless the target profile includes support for variables of that type. ### Use of Advanced Output Code: `Qsc.CapabilitiesCk.UseOfAdvancedOutput` This indicates that the program uses an entry callable or expression that has an unsupported type such as a `String` or user-defined type as part of the output when compiling for a target profile that does not support variables of that type. A type cannot be included in the output of a program unless the target profile includes support for variables of that type.