Skip to content

Commit 1a2e934

Browse files
authored
Ignore dynamic Fact (#3098)
When performing codgen, partial evaluation will ignore calls to `Std.Diagnostics.Fact` when the condition is dynamic (ie: not known at compile time). This is more permissive than the current behavior, where any `Fact` that is not provable true at compile time triggers a failure.
1 parent 766ac7d commit 1a2e934

File tree

4 files changed

+119
-66
lines changed

4 files changed

+119
-66
lines changed

library/std/src/Std/Diagnostics.qs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,17 +154,18 @@ operation CheckAllZero(qubits : Qubit[]) : Bool {
154154
}
155155

156156
/// # Summary
157-
/// Checks whether a given condition is true, failing with a message if it is not.
157+
/// Checks whether a given condition is false, failing with a message if it is.
158158
///
159159
/// # Description
160-
/// This function checks whether a given condition is true. If the condition is false, the operation fails with the given message,
160+
/// This function checks the given condition. If the condition is false, the operation fails with the given message,
161161
/// terminating the program.
162162
///
163163
/// # Input
164164
/// ## actual
165165
/// The condition to check.
166166
/// ## message
167167
/// The message to use in the failure if the condition is false.
168+
@SimulatableIntrinsic()
168169
function Fact(actual : Bool, message : String) : Unit {
169170
if (not actual) {
170171
fail message;

source/compiler/qsc_partial_eval/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1777,7 +1777,8 @@ impl<'a> PartialEvaluator<'a> {
17771777
| "ApplyIdleNoise"
17781778
| "GlobalPhase"
17791779
| "Message"
1780-
| "PostSelectZ" => Ok(Value::unit()),
1780+
| "PostSelectZ"
1781+
| "Fact" => Ok(Value::unit()),
17811782
"CheckZero" => Err(Error::UnsupportedSimulationIntrinsic(
17821783
"CheckZero".to_string(),
17831784
callee_expr_span,

source/compiler/qsc_partial_eval/src/tests/debug_metadata.rs

Lines changed: 63 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ fn one_gate() {
5858
5959
dbg_scopes:
6060
0 = SubProgram name=Main location=(2-40)
61-
1 = SubProgram name=H location=(1-111218)
61+
1 = SubProgram name=H location=(1-111225)
6262
dbg_locations:
6363
[1]: scope=0 location=(2-99)
64-
[2]: scope=1 location=(1-111290) inlined_at=1"#]],
64+
[2]: scope=1 location=(1-111297) inlined_at=1"#]],
6565
);
6666
}
6767

@@ -93,15 +93,15 @@ fn one_measurement() {
9393
9494
dbg_scopes:
9595
0 = SubProgram name=Main location=(2-40)
96-
1 = SubProgram name=H location=(1-111218)
97-
2 = SubProgram name=M location=(1-112927)
98-
3 = SubProgram name=Measure location=(1-113843)
96+
1 = SubProgram name=H location=(1-111225)
97+
2 = SubProgram name=M location=(1-112934)
98+
3 = SubProgram name=Measure location=(1-113850)
9999
dbg_locations:
100100
[1]: scope=0 location=(2-103)
101-
[2]: scope=1 location=(1-111290) inlined_at=1
101+
[2]: scope=1 location=(1-111297) inlined_at=1
102102
[3]: scope=0 location=(2-126)
103-
[4]: scope=2 location=(1-112969) inlined_at=3
104-
[6]: scope=3 location=(1-114156) inlined_at=4"#]],
103+
[4]: scope=2 location=(1-112976) inlined_at=3
104+
[6]: scope=3 location=(1-114163) inlined_at=4"#]],
105105
);
106106
}
107107

@@ -136,14 +136,14 @@ fn calls_to_other_callables() {
136136
dbg_scopes:
137137
0 = SubProgram name=Main location=(2-40)
138138
1 = SubProgram name=Foo location=(2-138)
139-
2 = SubProgram name=H location=(1-111218)
140-
3 = SubProgram name=MResetZ location=(1-182267)
139+
2 = SubProgram name=H location=(1-111225)
140+
3 = SubProgram name=MResetZ location=(1-182274)
141141
dbg_locations:
142142
[1]: scope=0 location=(2-99)
143143
[2]: scope=1 location=(2-179) inlined_at=1
144-
[3]: scope=2 location=(1-111290) inlined_at=2
144+
[3]: scope=2 location=(1-111297) inlined_at=2
145145
[4]: scope=0 location=(2-115)
146-
[5]: scope=3 location=(1-182316) inlined_at=4"#]],
146+
[5]: scope=3 location=(1-182323) inlined_at=4"#]],
147147
);
148148
}
149149

@@ -189,27 +189,27 @@ fn classical_for_loop() {
189189
0 = SubProgram name=Main location=(2-40)
190190
1 = LexicalBlockFile location=(2-99) discriminator=1
191191
2 = SubProgram name=Foo location=(2-156)
192-
3 = SubProgram name=X location=(1-134016)
193-
4 = SubProgram name=Y location=(1-135238)
192+
3 = SubProgram name=X location=(1-134023)
193+
4 = SubProgram name=Y location=(1-135245)
194194
5 = LexicalBlockFile location=(2-99) discriminator=2
195195
6 = LexicalBlockFile location=(2-99) discriminator=3
196196
dbg_locations:
197197
[1]: scope=0 location=(2-99)
198198
[2]: scope=1 location=(2-127) inlined_at=1
199199
[3]: scope=2 location=(2-197) inlined_at=2
200-
[4]: scope=3 location=(1-134088) inlined_at=3
200+
[4]: scope=3 location=(1-134095) inlined_at=3
201201
[5]: scope=2 location=(2-211) inlined_at=2
202-
[6]: scope=4 location=(1-135310) inlined_at=5
202+
[6]: scope=4 location=(1-135317) inlined_at=5
203203
[7]: scope=5 location=(2-127) inlined_at=1
204204
[8]: scope=2 location=(2-197) inlined_at=7
205-
[9]: scope=3 location=(1-134088) inlined_at=8
205+
[9]: scope=3 location=(1-134095) inlined_at=8
206206
[10]: scope=2 location=(2-211) inlined_at=7
207-
[11]: scope=4 location=(1-135310) inlined_at=10
207+
[11]: scope=4 location=(1-135317) inlined_at=10
208208
[12]: scope=6 location=(2-127) inlined_at=1
209209
[13]: scope=2 location=(2-197) inlined_at=12
210-
[14]: scope=3 location=(1-134088) inlined_at=13
210+
[14]: scope=3 location=(1-134095) inlined_at=13
211211
[15]: scope=2 location=(2-211) inlined_at=12
212-
[16]: scope=4 location=(1-135310) inlined_at=15"#]],
212+
[16]: scope=4 location=(1-135317) inlined_at=15"#]],
213213
);
214214
}
215215

@@ -280,7 +280,7 @@ fn nested_classical_for_loop() {
280280
5 = LexicalBlockFile location=(2-101) discriminator=1
281281
6 = LexicalBlockFile location=(2-129) discriminator=1
282282
7 = SubProgram name=Foo location=(2-208)
283-
8 = SubProgram name=X location=(1-134016)
283+
8 = SubProgram name=X location=(1-134023)
284284
9 = LexicalBlockFile location=(2-129) discriminator=2
285285
10 = LexicalBlockFile location=(2-129) discriminator=3
286286
11 = LexicalBlockFile location=(2-101) discriminator=2
@@ -290,33 +290,33 @@ fn nested_classical_for_loop() {
290290
[6]: scope=5 location=(2-129) inlined_at=5
291291
[7]: scope=6 location=(2-161) inlined_at=6
292292
[8]: scope=7 location=(2-249) inlined_at=7
293-
[9]: scope=8 location=(1-134088) inlined_at=8
293+
[9]: scope=8 location=(1-134095) inlined_at=8
294294
[10]: scope=9 location=(2-161) inlined_at=6
295295
[11]: scope=7 location=(2-249) inlined_at=10
296-
[12]: scope=8 location=(1-134088) inlined_at=11
296+
[12]: scope=8 location=(1-134095) inlined_at=11
297297
[13]: scope=10 location=(2-161) inlined_at=6
298298
[14]: scope=7 location=(2-249) inlined_at=13
299-
[15]: scope=8 location=(1-134088) inlined_at=14
299+
[15]: scope=8 location=(1-134095) inlined_at=14
300300
[16]: scope=11 location=(2-129) inlined_at=5
301301
[17]: scope=6 location=(2-161) inlined_at=16
302302
[18]: scope=7 location=(2-249) inlined_at=17
303-
[19]: scope=8 location=(1-134088) inlined_at=18
303+
[19]: scope=8 location=(1-134095) inlined_at=18
304304
[20]: scope=9 location=(2-161) inlined_at=16
305305
[21]: scope=7 location=(2-249) inlined_at=20
306-
[22]: scope=8 location=(1-134088) inlined_at=21
306+
[22]: scope=8 location=(1-134095) inlined_at=21
307307
[23]: scope=10 location=(2-161) inlined_at=16
308308
[24]: scope=7 location=(2-249) inlined_at=23
309-
[25]: scope=8 location=(1-134088) inlined_at=24
309+
[25]: scope=8 location=(1-134095) inlined_at=24
310310
[26]: scope=12 location=(2-129) inlined_at=5
311311
[27]: scope=6 location=(2-161) inlined_at=26
312312
[28]: scope=7 location=(2-249) inlined_at=27
313-
[29]: scope=8 location=(1-134088) inlined_at=28
313+
[29]: scope=8 location=(1-134095) inlined_at=28
314314
[30]: scope=9 location=(2-161) inlined_at=26
315315
[31]: scope=7 location=(2-249) inlined_at=30
316-
[32]: scope=8 location=(1-134088) inlined_at=31
316+
[32]: scope=8 location=(1-134095) inlined_at=31
317317
[33]: scope=10 location=(2-161) inlined_at=26
318318
[34]: scope=7 location=(2-249) inlined_at=33
319-
[35]: scope=8 location=(1-134088) inlined_at=34"#]],
319+
[35]: scope=8 location=(1-134095) inlined_at=34"#]],
320320
);
321321
}
322322

@@ -345,11 +345,11 @@ fn lambda() {
345345
dbg_scopes:
346346
0 = SubProgram name=Main location=(2-1)
347347
1 = SubProgram name=<lambda> location=(2-65)
348-
2 = SubProgram name=H location=(1-111218)
348+
2 = SubProgram name=H location=(1-111225)
349349
dbg_locations:
350350
[1]: scope=0 location=(2-99)
351351
[2]: scope=1 location=(2-82) inlined_at=1
352-
[3]: scope=2 location=(1-111290) inlined_at=2"#]],
352+
[3]: scope=2 location=(1-111297) inlined_at=2"#]],
353353
);
354354
}
355355

@@ -392,22 +392,22 @@ fn result_comparison_to_literal() {
392392
393393
dbg_scopes:
394394
0 = SubProgram name=Main location=(2-22)
395-
1 = SubProgram name=H location=(1-111218)
396-
2 = SubProgram name=M location=(1-112927)
397-
3 = SubProgram name=Measure location=(1-113843)
398-
4 = SubProgram name=X location=(1-134016)
399-
5 = SubProgram name=Reset location=(1-117316)
395+
1 = SubProgram name=H location=(1-111225)
396+
2 = SubProgram name=M location=(1-112934)
397+
3 = SubProgram name=Measure location=(1-113850)
398+
4 = SubProgram name=X location=(1-134023)
399+
5 = SubProgram name=Reset location=(1-117323)
400400
dbg_locations:
401401
[1]: scope=0 location=(2-86)
402-
[2]: scope=1 location=(1-111290) inlined_at=1
402+
[2]: scope=1 location=(1-111297) inlined_at=1
403403
[3]: scope=0 location=(2-110)
404-
[4]: scope=2 location=(1-112969) inlined_at=3
405-
[6]: scope=3 location=(1-114156) inlined_at=4
404+
[4]: scope=2 location=(1-112976) inlined_at=3
405+
[6]: scope=3 location=(1-114163) inlined_at=4
406406
[8]: scope=0 location=(2-154)
407-
[9]: scope=4 location=(1-134088) inlined_at=8
407+
[9]: scope=4 location=(1-134095) inlined_at=8
408408
[10]: scope=0 location=(2-125)
409409
[11]: scope=0 location=(2-179)
410-
[12]: scope=5 location=(1-117360) inlined_at=11"#]],
410+
[12]: scope=5 location=(1-117367) inlined_at=11"#]],
411411
);
412412
}
413413

@@ -457,25 +457,25 @@ fn if_else() {
457457
458458
dbg_scopes:
459459
0 = SubProgram name=Main location=(2-22)
460-
1 = SubProgram name=H location=(1-111218)
461-
2 = SubProgram name=M location=(1-112927)
462-
3 = SubProgram name=Measure location=(1-113843)
463-
4 = SubProgram name=X location=(1-134016)
464-
5 = SubProgram name=Y location=(1-135238)
460+
1 = SubProgram name=H location=(1-111225)
461+
2 = SubProgram name=M location=(1-112934)
462+
3 = SubProgram name=Measure location=(1-113850)
463+
4 = SubProgram name=X location=(1-134023)
464+
5 = SubProgram name=Y location=(1-135245)
465465
dbg_locations:
466466
[2]: scope=0 location=(2-112)
467-
[3]: scope=1 location=(1-111290) inlined_at=2
467+
[3]: scope=1 location=(1-111297) inlined_at=2
468468
[4]: scope=0 location=(2-135)
469-
[5]: scope=2 location=(1-112969) inlined_at=4
470-
[7]: scope=3 location=(1-114156) inlined_at=5
469+
[5]: scope=2 location=(1-112976) inlined_at=4
470+
[7]: scope=3 location=(1-114163) inlined_at=5
471471
[9]: scope=0 location=(2-176)
472-
[10]: scope=4 location=(1-134088) inlined_at=9
472+
[10]: scope=4 location=(1-134095) inlined_at=9
473473
[11]: scope=0 location=(2-212)
474-
[12]: scope=5 location=(1-135310) inlined_at=11
474+
[12]: scope=5 location=(1-135317) inlined_at=11
475475
[13]: scope=0 location=(2-150)
476476
[14]: scope=0 location=(2-246)
477-
[15]: scope=2 location=(1-112969) inlined_at=14
478-
[17]: scope=3 location=(1-114156) inlined_at=15"#]],
477+
[15]: scope=2 location=(1-112976) inlined_at=14
478+
[17]: scope=3 location=(1-114163) inlined_at=15"#]],
479479
);
480480
}
481481

@@ -517,20 +517,20 @@ fn branch_due_to_binop_short_circuit() {
517517
518518
dbg_scopes:
519519
0 = SubProgram name=Main location=(2-1)
520-
1 = SubProgram name=H location=(1-111218)
521-
2 = SubProgram name=M location=(1-112927)
522-
3 = SubProgram name=Measure location=(1-113843)
520+
1 = SubProgram name=H location=(1-111225)
521+
2 = SubProgram name=M location=(1-112934)
522+
3 = SubProgram name=Measure location=(1-113850)
523523
dbg_locations:
524524
[2]: scope=0 location=(2-75)
525-
[3]: scope=1 location=(1-111290) inlined_at=2
525+
[3]: scope=1 location=(1-111297) inlined_at=2
526526
[4]: scope=0 location=(2-86)
527-
[5]: scope=1 location=(1-111290) inlined_at=4
527+
[5]: scope=1 location=(1-111297) inlined_at=4
528528
[6]: scope=0 location=(2-107)
529-
[7]: scope=2 location=(1-112969) inlined_at=6
530-
[9]: scope=3 location=(1-114156) inlined_at=7
529+
[7]: scope=2 location=(1-112976) inlined_at=6
530+
[9]: scope=3 location=(1-114163) inlined_at=7
531531
[11]: scope=0 location=(2-129)
532-
[12]: scope=2 location=(1-112969) inlined_at=11
533-
[14]: scope=3 location=(1-114156) inlined_at=12
532+
[12]: scope=2 location=(1-112976) inlined_at=11
533+
[14]: scope=3 location=(1-114163) inlined_at=12
534534
[16]: scope=0 location=(2-127)"#]],
535535
);
536536
}

source/compiler/qsc_partial_eval/src/tests/misc.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,3 +800,54 @@ fn double_to_integer_conversion() {
800800
Jump(1)"#]],
801801
);
802802
}
803+
804+
#[test]
805+
fn dynamic_fact_call_ignored() {
806+
let program = get_rir_program(indoc! {
807+
r#"
808+
namespace Test {
809+
@EntryPoint()
810+
operation Main() : Bool {
811+
use q = Qubit();
812+
let b = M(q) == One;
813+
Std.Diagnostics.Fact(not b, "measurement should always be zero");
814+
b
815+
}
816+
}
817+
"#,
818+
});
819+
820+
assert_blocks(
821+
&program,
822+
&expect![[r#"
823+
Blocks:
824+
Block 0:Block:
825+
Call id(1), args( Pointer, )
826+
Call id(2), args( Qubit(0), Result(0), )
827+
Variable(0, Boolean) = Call id(3), args( Result(0), )
828+
Variable(1, Boolean) = Store Variable(0, Boolean)
829+
Variable(2, Boolean) = Store Variable(1, Boolean)
830+
Variable(3, Boolean) = LogicalNot Variable(2, Boolean)
831+
Variable(4, Boolean) = Store Variable(2, Boolean)
832+
Call id(4), args( Variable(4, Boolean), Tag(0, 3), )
833+
Return"#]],
834+
);
835+
}
836+
837+
#[test]
838+
fn static_fact_call_evaluated() {
839+
let error = get_partial_evaluation_error(indoc! {
840+
r#"
841+
namespace Test {
842+
@EntryPoint()
843+
operation Main() : Unit {
844+
Std.Diagnostics.Fact(false, "this should always fail");
845+
}
846+
}
847+
"#,
848+
});
849+
// Note that we don't use `assert_error` with an `expect!` here because it includes
850+
// a `PackageSpan` in the error message which is points to the stdlib and can be noisy when
851+
// libraries are updated.
852+
assert!(format!("{error:?}").contains("this should always fail"));
853+
}

0 commit comments

Comments
 (0)