Skip to content

Commit 76956d4

Browse files
committed
Fixing reported issues
1 parent 466f059 commit 76956d4

File tree

23 files changed

+451
-107
lines changed

23 files changed

+451
-107
lines changed

compiler/qsc_qasm/src/semantic/error.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ pub enum SemanticErrorKind {
103103
#[error("for statements must have a body or statement")]
104104
#[diagnostic(code("Qasm.Lowerer.ForStatementsMustHaveABodyOrStatement"))]
105105
ForStatementsMustHaveABodyOrStatement(#[label] Span),
106+
#[error("gate declarations must be done in global scope")]
107+
#[diagnostic(code("Qasm.Lowerer.GateDeclarationInNonGlobalScope"))]
108+
GateDeclarationInNonGlobalScope(#[label] Span),
106109
#[error("if statement missing {0} expression")]
107110
#[diagnostic(code("Qasm.Lowerer.IfStmtMissingExpression"))]
108111
IfStmtMissingExpression(String, #[label] Span),
@@ -169,9 +172,9 @@ pub enum SemanticErrorKind {
169172
#[error("pow gate modifiers must have an exponent")]
170173
#[diagnostic(code("Qasm.Lowerer.PowModifierMustHaveExponent"))]
171174
PowModifierMustHaveExponent(#[label] Span),
172-
#[error("quantum declarations must be done in global scope")]
173-
#[diagnostic(code("Qasm.Lowerer.QuantumDeclarationInNonGlobalScope"))]
174-
QuantumDeclarationInNonGlobalScope(#[label] Span),
175+
#[error("qubit declarations must be done in global scope")]
176+
#[diagnostic(code("Qasm.Lowerer.QubitDeclarationInNonGlobalScope"))]
177+
QubitDeclarationInNonGlobalScope(#[label] Span),
175178
#[error("quantum typed values cannot be used in binary expressions")]
176179
#[diagnostic(code("Qasm.Lowerer.QuantumTypesInBinaryExpression"))]
177180
QuantumTypesInBinaryExpression(#[label] Span),

compiler/qsc_qasm/src/semantic/lowerer.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,10 +1401,14 @@ impl Lowerer {
14011401

14021402
fn lower_expr_stmt(&mut self, stmt: &syntax::ExprStmt) -> semantic::StmtKind {
14031403
let expr = self.lower_expr(&stmt.expr);
1404+
if matches!(&*expr.kind, semantic::ExprKind::Err) {
1405+
semantic::StmtKind::Err
1406+
} else {
14041407
semantic::StmtKind::ExprStmt(semantic::ExprStmt {
14051408
span: stmt.span,
14061409
expr,
14071410
})
1411+
}
14081412
}
14091413

14101414
fn lower_extern(&mut self, stmt: &syntax::ExternDecl) -> semantic::StmtKind {
@@ -2038,7 +2042,7 @@ impl Lowerer {
20382042
// 1. Check that we are in the global scope. QASM3 semantics
20392043
// only allow gate definitions in the global scope.
20402044
if !self.symbols.is_current_scope_global() {
2041-
let kind = SemanticErrorKind::QuantumDeclarationInNonGlobalScope(stmt.span);
2045+
let kind = SemanticErrorKind::GateDeclarationInNonGlobalScope(stmt.span);
20422046
self.push_semantic_error(kind);
20432047
}
20442048

@@ -2124,6 +2128,11 @@ impl Lowerer {
21242128
}
21252129

21262130
fn lower_quantum_decl(&mut self, stmt: &syntax::QubitDeclaration) -> semantic::StmtKind {
2131+
if !self.symbols.is_current_scope_global() {
2132+
let kind = SemanticErrorKind::QubitDeclarationInNonGlobalScope(stmt.span);
2133+
self.push_semantic_error(kind);
2134+
}
2135+
21272136
// If there wasn't an explicit size, infer the size to be 1.
21282137
let (ty, size_and_span) = if let Some(size_expr) = &stmt.size {
21292138
let size_expr = self.lower_expr(size_expr);
@@ -3510,15 +3519,18 @@ impl Lowerer {
35103519
fn lower_const_range(&mut self, range: &syntax::Range) -> Option<semantic::Range> {
35113520
let mut lower_and_const_eval = |expr| {
35123521
let lowered_expr = self.lower_expr(expr);
3513-
let lit = lowered_expr.const_eval(self);
3514-
lit.map(|lit| {
3515-
let lit_expr = semantic::Expr {
3522+
let lit_expr = Self::try_cast_expr_to_type(&Type::Int(None, true), &lowered_expr);
3523+
let Some(lowered_expr) = lit_expr else {
3524+
self.push_invalid_cast_error(&Type::Int(None, true), &lowered_expr.ty, expr.span);
3525+
return None;
3526+
};
3527+
// const_eval will push any needed errors
3528+
let lit = lowered_expr.const_eval(self)?;
3529+
3530+
Some(semantic::Expr {
35163531
span: lowered_expr.span,
35173532
kind: Box::new(semantic::ExprKind::Lit(lit.clone())),
3518-
ty: lowered_expr.ty,
3519-
};
3520-
// Range components (start, step, end) can be negative, so we coerce to an `int`.
3521-
self.coerce_literal_expr_to_type(&Type::Int(None, true), &lit_expr, &lit)
3533+
ty: Type::Int(None, true),
35223534
})
35233535
};
35243536

compiler/qsc_qasm/src/semantic/tests/decls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod extern_decl;
1111
mod float;
1212
mod int;
1313
mod qreg;
14+
mod qubit;
1415
mod stretch;
1516
mod uint;
1617

compiler/qsc_qasm/src/semantic/tests/decls/qreg.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,33 @@ fn with_no_init_expr() {
1515
);
1616
}
1717

18+
#[test]
19+
fn with_no_init_expr_in_non_global_scope() {
20+
check_stmt_kind(
21+
"{qreg a;}",
22+
&expect![[r#"
23+
Program:
24+
version: <none>
25+
statements:
26+
Stmt [0-9]:
27+
annotations: <empty>
28+
kind: Block [0-9]:
29+
Stmt [1-8]:
30+
annotations: <empty>
31+
kind: QubitDeclaration [1-8]:
32+
symbol_id: 8
33+
34+
[Qasm.Lowerer.QubitDeclarationInNonGlobalScope
35+
36+
x qubit declarations must be done in global scope
37+
,-[test:1:2]
38+
1 | {qreg a;}
39+
: ^^^^^^^
40+
`----
41+
]"#]],
42+
);
43+
}
44+
1845
#[test]
1946
fn array_with_no_init_expr() {
2047
check_stmt_kind(
@@ -26,3 +53,32 @@ fn array_with_no_init_expr() {
2653
size_span: [7-8]"#]],
2754
);
2855
}
56+
57+
#[test]
58+
fn array_with_no_init_expr_in_non_global_scope() {
59+
check_stmt_kind(
60+
"{qreg a[3];}",
61+
&expect![[r#"
62+
Program:
63+
version: <none>
64+
statements:
65+
Stmt [0-12]:
66+
annotations: <empty>
67+
kind: Block [0-12]:
68+
Stmt [1-11]:
69+
annotations: <empty>
70+
kind: QubitArrayDeclaration [1-11]:
71+
symbol_id: 8
72+
size: 3
73+
size_span: [8-9]
74+
75+
[Qasm.Lowerer.QubitDeclarationInNonGlobalScope
76+
77+
x qubit declarations must be done in global scope
78+
,-[test:1:2]
79+
1 | {qreg a[3];}
80+
: ^^^^^^^^^^
81+
`----
82+
]"#]],
83+
);
84+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use expect_test::expect;
5+
6+
use crate::semantic::tests::check_stmt_kind;
7+
8+
#[test]
9+
fn with_no_init_expr() {
10+
check_stmt_kind(
11+
"qubit a;",
12+
&expect![[r#"
13+
QubitDeclaration [0-8]:
14+
symbol_id: 8"#]],
15+
);
16+
}
17+
18+
#[test]
19+
fn with_no_init_expr_in_non_global_scope() {
20+
check_stmt_kind(
21+
"{qubit a;}",
22+
&expect![[r#"
23+
Program:
24+
version: <none>
25+
statements:
26+
Stmt [0-10]:
27+
annotations: <empty>
28+
kind: Block [0-10]:
29+
Stmt [1-9]:
30+
annotations: <empty>
31+
kind: QubitDeclaration [1-9]:
32+
symbol_id: 8
33+
34+
[Qasm.Lowerer.QubitDeclarationInNonGlobalScope
35+
36+
x qubit declarations must be done in global scope
37+
,-[test:1:2]
38+
1 | {qubit a;}
39+
: ^^^^^^^^
40+
`----
41+
]"#]],
42+
);
43+
}
44+
45+
#[test]
46+
fn array_with_no_init_expr() {
47+
check_stmt_kind(
48+
"qubit[3] a;",
49+
&expect![[r#"
50+
QubitArrayDeclaration [0-11]:
51+
symbol_id: 8
52+
size: 3
53+
size_span: [6-7]"#]],
54+
);
55+
}
56+
57+
#[test]
58+
fn array_with_no_init_expr_in_non_global_scope() {
59+
check_stmt_kind(
60+
"{qubit[3] a;}",
61+
&expect![[r#"
62+
Program:
63+
version: <none>
64+
statements:
65+
Stmt [0-13]:
66+
annotations: <empty>
67+
kind: Block [0-13]:
68+
Stmt [1-12]:
69+
annotations: <empty>
70+
kind: QubitArrayDeclaration [1-12]:
71+
symbol_id: 8
72+
size: 3
73+
size_span: [7-8]
74+
75+
[Qasm.Lowerer.QubitDeclarationInNonGlobalScope
76+
77+
x qubit declarations must be done in global scope
78+
,-[test:1:2]
79+
1 | {qubit[3] a;}
80+
: ^^^^^^^^^^^
81+
`----
82+
]"#]],
83+
);
84+
}

compiler/qsc_qasm/src/semantic/tests/expression/indexing.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,7 @@ fn array_slice_with_zero_step_errors() {
250250
kind: Lit: Bitstring("00010000")
251251
Stmt [32-39]:
252252
annotations: <empty>
253-
kind: ExprStmt [32-39]:
254-
expr: Expr [32-38]:
255-
ty: Err
256-
kind: Err
253+
kind: Err
257254
258255
[Qasm.Lowerer.ZeroStepInRange
259256

compiler/qsc_qasm/src/tests/fuzz.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,41 @@ fn fuzz_2348() {
9191
super::compare_qasm_and_qasharp_asts(source);
9292
compile_qasm_best_effort(source, Profile::Unrestricted);
9393
}
94+
95+
#[test]
96+
#[ignore = "Requires further investigation"]
97+
fn fuzz_2366() {
98+
let source = "t[:π";
99+
super::compare_qasm_and_qasharp_asts(source);
100+
compile_qasm_best_effort(source, Profile::Unrestricted);
101+
}
102+
103+
#[test]
104+
fn fuzz_2368() {
105+
let source = "c[:0s";
106+
super::compare_qasm_and_qasharp_asts(source);
107+
compile_qasm_best_effort(source, Profile::Unrestricted);
108+
}
109+
110+
#[test]
111+
#[ignore = "Requires further investigation"]
112+
fn fuzz_2379() {
113+
let source = "1[true:";
114+
super::compare_qasm_and_qasharp_asts(source);
115+
compile_qasm_best_effort(source, Profile::Unrestricted);
116+
}
117+
118+
#[test]
119+
fn fuzz_2391() {
120+
let source = "c[:0s";
121+
super::compare_qasm_and_qasharp_asts(source);
122+
compile_qasm_best_effort(source, Profile::Unrestricted);
123+
}
124+
125+
#[test]
126+
#[ignore = "Requires further investigation"]
127+
fn fuzz_2392() {
128+
let source = "e[π:";
129+
super::compare_qasm_and_qasharp_asts(source);
130+
compile_qasm_best_effort(source, Profile::Unrestricted);
131+
}

language_service/src/compilation.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ impl Compilation {
264264
.collect::<InMemorySourceResolver>();
265265
let capabilities = target_profile.into();
266266

267-
let CompileRawQasmResult(store, source_package_id, dependencies, _sig, compile_errors) =
267+
let CompileRawQasmResult(store, source_package_id, dependencies, _sig, mut compile_errors) =
268268
qsc::qasm::compile_raw_qasm(
269269
source.clone(),
270270
path.clone(),
@@ -273,6 +273,18 @@ impl Compilation {
273273
capabilities,
274274
);
275275

276+
let unit = store
277+
.get(source_package_id)
278+
.expect("expected to find user package");
279+
280+
run_fir_passes(
281+
&mut compile_errors,
282+
target_profile,
283+
&store,
284+
source_package_id,
285+
unit,
286+
);
287+
276288
Self {
277289
package_store: store,
278290
user_package_id: source_package_id,

language_service/src/lib.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,22 +117,26 @@ impl LanguageService {
117117
/// This is the "entry point" for the language service's logic, after its constructor.
118118
///
119119
/// LSP: textDocument/didOpen, textDocument/didChange
120-
pub fn update_document(&mut self, uri: &str, version: u32, text: &str) {
120+
pub fn update_document(&mut self, uri: &str, version: u32, text: &str, language_id: &str) {
121121
trace!("update_document: {uri} {version}");
122122
self.send_update(Update::Document {
123123
uri: uri.into(),
124124
version,
125125
text: text.into(),
126+
language_id: language_id.into(),
126127
});
127128
}
128129

129130
/// Indicates that the client is no longer interested in the document,
130131
/// typically occurs when the document is closed in the editor.
131132
///
132133
/// LSP: textDocument/didClose
133-
pub fn close_document(&mut self, uri: &str) {
134+
pub fn close_document(&mut self, uri: &str, language_id: &str) {
134135
trace!("close_document: {uri}");
135-
self.send_update(Update::CloseDocument { uri: uri.into() });
136+
self.send_update(Update::CloseDocument {
137+
uri: uri.into(),
138+
language_id: language_id.into(),
139+
});
136140
}
137141

138142
/// The uri refers to the notebook itself, not any of the individual cells.
@@ -424,11 +428,18 @@ fn push_update(pending_updates: &mut Vec<Update>, update: Update) {
424428

425429
async fn apply_update(updater: &mut CompilationStateUpdater<'_>, update: Update) {
426430
match update {
427-
Update::CloseDocument { uri } => {
428-
updater.close_document(&uri).await;
431+
Update::CloseDocument { uri, language_id } => {
432+
updater.close_document(&uri, &language_id).await;
429433
}
430-
Update::Document { uri, version, text } => {
431-
updater.update_document(&uri, version, &text).await;
434+
Update::Document {
435+
uri,
436+
version,
437+
text,
438+
language_id,
439+
} => {
440+
updater
441+
.update_document(&uri, version, &text, &language_id)
442+
.await;
432443
}
433444
Update::NotebookDocument {
434445
notebook_uri,
@@ -462,9 +473,11 @@ enum Update {
462473
uri: String,
463474
version: u32,
464475
text: String,
476+
language_id: String,
465477
},
466478
CloseDocument {
467479
uri: String,
480+
language_id: String,
468481
},
469482
NotebookDocument {
470483
notebook_uri: String,

0 commit comments

Comments
 (0)