Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions source/compiler/qsc_frontend/src/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@ pub(super) enum Error {
#[diagnostic(code("Qsc.Resolve.NotFound"))]
NotAvailable(String, String, #[label] Span),

#[error("`Qubit` not found")]
#[diagnostic(help(
"to allocate qubits, use syntax like `use q = Qubit();` or `use qs = Qubit[N];` or `use (q1, q2) = (Qubit(), Qubit());`"
))]
#[diagnostic(code("Qsc.Resolve.NotFoundQubit"))]
NotFoundQubit(#[label] Span),

#[error("use of unimplemented item `{0}`")]
#[diagnostic(help("this item is not implemented and cannot be used"))]
#[diagnostic(code("Qsc.Resolve.Unimplemented"))]
Expand Down Expand Up @@ -772,6 +779,8 @@ impl Resolver {
format!("{}.{}", dropped_name.namespace, dropped_name.name),
span,
))
} else if name == "Qubit" {
Err(Error::NotFoundQubit(span))
} else {
Err(Error::NotFound(name, span))
}
Expand Down
44 changes: 44 additions & 0 deletions source/compiler/qsc_frontend/src/resolve/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2341,6 +2341,50 @@ fn resolve_local_generic() {
);
}

#[test]
fn incorrect_single_qubit_allocation_syntax_gets_extra_help() {
check(
indoc! {"
namespace A {
operation B() : Unit {
let q = Qubit();
}
}
"},
&expect![[r#"
namespace namespace3 {
operation package2_item1() : Unit {
let local13 = Qubit();
}
}

// NotFoundQubit(Span { lo: 57, hi: 62 })
"#]],
);
}

#[test]
fn incorrect_qubit_array_allocation_syntax_gets_extra_help() {
check(
indoc! {"
namespace A {
operation B() : Unit {
let q = Qubit[5];
}
}
"},
&expect![[r#"
namespace namespace3 {
operation package2_item1() : Unit {
let local13 = Qubit[5];
}
}

// NotFoundQubit(Span { lo: 57, hi: 62 })
"#]],
);
}

#[test]
fn dropped_base_callable_from_unrestricted() {
check_with_capabilities(
Expand Down
32 changes: 16 additions & 16 deletions source/compiler/qsc_parse/src/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ fn parse_qubit(s: &mut ParserContext) -> Result<Box<StmtKind>> {
}

fn parse_qubit_init(s: &mut ParserContext) -> Result<Box<QubitInit>> {
let help_text = "to allocate qubits, use syntax like `use q = Qubit();` or `use qs = Qubit[N];` or `use (q1, q2) = (Qubit(), Qubit());`";
let lo = s.peek().span.lo;
s.expect(WordKinds::Qubit);
let kind = if let Ok(name) = ident(s) {
Expand All @@ -162,33 +163,32 @@ fn parse_qubit_init(s: &mut ParserContext) -> Result<Box<QubitInit>> {
"qubit initializer",
"identifier",
name.span,
)));
))
.with_help(help_text));
} else if token(s, TokenKind::Open(Delim::Paren)).is_ok() {
token(s, TokenKind::Close(Delim::Paren))?;
token(s, TokenKind::Close(Delim::Paren)).map_err(|e| e.with_help(help_text))?;
QubitInitKind::Single
} else if token(s, TokenKind::Open(Delim::Bracket)).is_ok() {
let size = expr(s)?;
token(s, TokenKind::Close(Delim::Bracket))?;
let size = expr(s).map_err(|e| e.with_help(help_text))?;
token(s, TokenKind::Close(Delim::Bracket)).map_err(|e| e.with_help(help_text))?;
QubitInitKind::Array(size)
} else {
let token = s.peek();
return Err(Error::new(ErrorKind::Rule(
"qubit suffix",
token.kind,
token.span,
)));
return Err(
Error::new(ErrorKind::Rule("qubit suffix", token.kind, token.span))
.with_help(help_text),
);
}
} else if token(s, TokenKind::Open(Delim::Paren)).is_ok() {
let (inits, final_sep) = seq(s, parse_qubit_init)?;
token(s, TokenKind::Close(Delim::Paren))?;
let (inits, final_sep) = seq(s, parse_qubit_init).map_err(|e| e.with_help(help_text))?;
token(s, TokenKind::Close(Delim::Paren)).map_err(|e| e.with_help(help_text))?;
final_sep.reify(inits, QubitInitKind::Paren, QubitInitKind::Tuple)
} else {
let token = s.peek();
return Err(Error::new(ErrorKind::Rule(
"qubit initializer",
token.kind,
token.span,
)));
return Err(
Error::new(ErrorKind::Rule("qubit initializer", token.kind, token.span))
.with_help(help_text),
);
};

Ok(Box::new(QubitInit {
Expand Down
3 changes: 3 additions & 0 deletions source/compiler/qsc_parse/src/stmt/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ fn use_invalid_init() {
hi: 14,
},
),
Some(
"to allocate qubits, use syntax like `use q = Qubit();` or `use qs = Qubit[N];` or `use (q1, q2) = (Qubit(), Qubit());`",
),
)
"#]],
);
Expand Down
Loading