Skip to content

Commit

Permalink
Support error Uri, update RCA error strings (#1575)
Browse files Browse the repository at this point in the history
This change adds support for error Uris by hooking the miette error
`.url()` to the VS Code and Monaco `target` field. It also updates the
wording on RCA check pass errors to use "configured target profile"
instead of "current target" for more clarification. A follow up PR can
update the error link(s) to point to more specific documentation pages.

In VS Code, the error links show up as a clickable error code:

![image](https://github.com/microsoft/qsharp/assets/10567287/95795422-3507-44ed-9277-73a63a12ab12)

In Python/Jupyter, the miette visualization is used which puts clickable
links next to the error code:

![image](https://github.com/microsoft/qsharp/assets/10567287/01e38445-ede4-4278-8c57-6540c472cfdc)

In Monaco (used in the playground) links work like the VS Code version:
<img width="692" alt="image"
src="https://github.com/microsoft/qsharp/assets/10567287/62bf56a2-83de-4a95-a443-b5119c363fe6">
  • Loading branch information
swernli authored May 29, 2024
1 parent d0346c4 commit 9aa8aaf
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 26 deletions.
57 changes: 32 additions & 25 deletions compiler/qsc_rca/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,158 +8,165 @@ use thiserror::Error;
use crate::RuntimeFeatureFlags;

#[derive(Clone, Debug, Diagnostic, Error)]
#[diagnostic(url("https://aka.ms/qdk.qir"))]
pub enum Error {
#[error("cannot use a dynamic bool value")]
#[diagnostic(help(
"using a bool value that depends on a measurement result is not supported by the current target"
"using a bool value that depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicBool"))]
UseOfDynamicBool(#[label] Span),

#[error("cannot use a dynamic integer value")]
#[diagnostic(help(
"using an integer value that depends on a measurement result is not supported by the current target"
"using an integer value that depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicInt"))]
UseOfDynamicInt(#[label] Span),

#[error("cannot use a dynamic Pauli value")]
#[diagnostic(help(
"using a Pauli value that depends on a measurement result is not supported by the current target"
"using a Pauli value that depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicPauli"))]
UseOfDynamicPauli(#[label] Span),

#[error("cannot use a dynamic Range value")]
#[diagnostic(help(
"using a Range value that depends on a measurement result is not supported by the current target"
"using a Range value that depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicRange"))]
UseOfDynamicRange(#[label] Span),

#[error("cannot use a dynamic double value")]
#[diagnostic(help(
"using a double value that depends on a measurement result is not supported by the current target"
"using a double value that depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicDouble"))]
UseOfDynamicDouble(#[label] Span),

#[error("cannot use a dynamic qubit")]
#[diagnostic(help(
"using a qubit whose allocation depends on a measurement result is not supported by the current target"
"using a qubit whose allocation depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicQubit"))]
UseOfDynamicQubit(#[label] Span),

#[error("cannot use a dynamic big integer value")]
#[diagnostic(help(
"using a big integer value that depends on a measurement result is not supported by the current target"
"using a big integer value that depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicBigInt"))]
UseOfDynamicBigInt(#[label] Span),

#[error("cannot use a dynamic string value")]
#[diagnostic(help(
"using a string value that depends on a measurement result is not supported by the current target"
"using a string value that depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicString"))]
UseOfDynamicString(#[label] Span),

#[error("cannot use a dynamic exponent")]
#[diagnostic(help(
"using an exponent that depends on a measurement result is not supported by the current target"
"using an exponent that depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicExponent"))]
UseOfDynamicExponent(#[label] Span),

#[error("cannot use a dynamically-sized array")]
#[diagnostic(help(
"using an array whose size depends on a measurement result is not supported by the current target"
"using an array whose size depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicallySizedArray"))]
UseOfDynamicallySizedArray(#[label] Span),

#[error("cannot use a dynamic user-defined type")]
#[diagnostic(help(
"using a user-defined type in which one or more of its members depend on a measurement result is not supported by the current target"
"using a user-defined type in which one or more of its members depend on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicUdt"))]
UseOfDynamicUdt(#[label] Span),

#[error("cannot use a dynamic function")]
#[diagnostic(help(
"using a function whose resolution depends on a measurement result is not supported by the current target"
"using a function whose resolution depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicArrowFunction"))]
UseOfDynamicArrowFunction(#[label] Span),

#[error("cannot use a dynamic operation")]
#[diagnostic(help(
"using an operation whose resolution depends on a measurement result is not supported by the current target"
"using an operation whose resolution depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicArrowOperation"))]
UseOfDynamicArrowOperation(#[label] Span),

#[error("cannot call a cyclic function with a dynamic value as argument")]
#[diagnostic(help(
"calling a cyclic function with an argument value that depends on a measurement result is not supported by the current target"
"calling a cyclic function with an argument value that depends on a measurement result is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.CallToCyclicFunctionWithDynamicArg"))]
CallToCyclicFunctionWithDynamicArg(#[label] Span),

#[error("cannot define a cyclic operation specialization")]
#[diagnostic(help("operation specializations that contain call cycles are not supported by the current target"))]
#[diagnostic(help("operation specializations that contain call cycles are not supported by the configured target profile"))]
#[diagnostic(code("Qsc.CapabilitiesCk.CyclicOperationSpec"))]
CyclicOperationSpec(#[label] Span),

#[error("cannot call a cyclic operation")]
#[diagnostic(help("calling an operation specialization that contains call cycles is not supported by the current target"))]
#[diagnostic(help("calling an operation specialization that contains call cycles is not supported by the configured target profile"))]
#[diagnostic(code("Qsc.CapabilitiesCk.CallToCyclicOperation"))]
CallToCyclicOperation(#[label] Span),

#[error("cannot call a function or operation whose resolution is dynamic")]
#[diagnostic(help("calling a function or operation whose resolution depends on a measurement result is not supported by the current target"))]
#[diagnostic(help("calling a function or operation whose resolution depends on a measurement result is not supported by the configured target profile"))]
#[diagnostic(code("Qsc.CapabilitiesCk.CallToDynamicCallee"))]
CallToDynamicCallee(#[label] Span),

#[error("cannot perform a measurement within a dynamic scope")]
#[diagnostic(help("performing a measurement within a scope that depends on a measurement result is not supported by the current target"))]
#[diagnostic(help("performing a measurement within a scope that depends on a measurement result is not supported by the configured target profile"))]
#[diagnostic(code("Qsc.CapabilitiesCk.MeasurementWithinDynamicScope"))]
MeasurementWithinDynamicScope(#[label] Span),

#[error("cannot access an array using a dynamic index")]
#[diagnostic(help("accessing an array using an index that depends on a measurement result is not supported by the current target"))]
#[diagnostic(help("accessing an array using an index that depends on a measurement result is not supported by the configured target profile"))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDynamicIndex"))]
UseOfDynamicIndex(#[label] Span),

#[error("cannot use a return within a dynamic scope")]
#[diagnostic(help("using a return within a scope that depends on a measurement result is not supported by the current target"))]
#[diagnostic(help("using a return within a scope that depends on a measurement result is not supported by the configured target profile"))]
#[diagnostic(code("Qsc.CapabilitiesCk.ReturnWithinDynamicScope"))]
ReturnWithinDynamicScope(#[label] Span),

#[error("cannot have a loop with a dynamic condition")]
#[diagnostic(help("using a loop with a condition that depends on a measurement result is not supported by the current target"))]
#[diagnostic(help("using a loop with a condition that depends on a measurement result is not supported by the configured target profile"))]
#[diagnostic(code("Qsc.CapabilitiesCk.LoopWithDynamicCondition"))]
LoopWithDynamicCondition(#[label] Span),

#[error("cannot use a bool value as an output")]
#[diagnostic(help("using a bool value as an output is not supported by the current target"))]
#[diagnostic(help(
"using a bool value as an output is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfBoolOutput"))]
UseOfBoolOutput(#[label] Span),

#[error("cannot use a double value as an output")]
#[diagnostic(help("using a Double as an output is not supported by the current target"))]
#[diagnostic(help(
"using a Double as an output is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfDoubleOutput"))]
UseOfDoubleOutput(#[label] Span),

#[error("cannot use an integer value as an output")]
#[diagnostic(help("using an integer as an output is not supported by the current target"))]
#[diagnostic(help(
"using an integer as an output is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfIntOutput"))]
UseOfIntOutput(#[label] Span),

#[error("cannot use value with advanced type as an output")]
#[diagnostic(help(
"using a value of type callable, range, big integer, Pauli, Qubit or string as an output is not supported by the current target"
"using a value of type callable, range, big integer, Pauli, Qubit or string as an output is not supported by the configured target profile"
))]
#[diagnostic(code("Qsc.CapabilitiesCk.UseOfAdvancedOutput"))]
UseOfAdvancedOutput(#[label] Span),
Expand Down
9 changes: 9 additions & 0 deletions playground/src/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ function VSDiagsToMarkers(errors: VSDiagnostic[]): monaco.editor.IMarkerData[] {
}),
};

if (err.uri && err.code) {
marker.code = {
value: err.code,
target: monaco.Uri.parse(err.uri),
};
} else if (err.code) {
marker.code = err.code;
}

return marker;
});
}
Expand Down
7 changes: 6 additions & 1 deletion vscode/src/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ export function toVsCodeDiagnostic(d: VSDiagnostic): vscode.Diagnostic {
d.message,
severity,
);
if (d.code) {
if (d.uri && d.code) {
vscodeDiagnostic.code = {
value: d.code,
target: vscode.Uri.parse(d.uri),
};
} else if (d.code) {
vscodeDiagnostic.code = d.code;
}
if (d.related) {
Expand Down
7 changes: 7 additions & 0 deletions wasm/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ serializable_type! {
pub severity: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub uri: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub related: Vec<Related>
},
Expand All @@ -27,6 +29,7 @@ serializable_type! {
message: string;
severity: "error" | "warning" | "info"
code?: string;
uri?: string;
related?: IRelatedInformation[];
}"#
}
Expand Down Expand Up @@ -141,6 +144,9 @@ impl VSDiagnostic {
// e.g. Qsc.Eval.ReleasedQubitNotZero
let code = err.code().map(|c| c.to_string());

// e.g. https://aka.ms/qdk.qir
let uri = err.url().map(|u| u.to_string());

Self {
range: range.into(),
severity: (match err.severity().unwrap_or(Severity::Error) {
Expand All @@ -151,6 +157,7 @@ impl VSDiagnostic {
.to_string(),
message,
code,
uri,
related,
}
}
Expand Down

0 comments on commit 9aa8aaf

Please sign in to comment.