Skip to content

Commit 18feb76

Browse files
authored
Merge pull request #28975 from ProvableHQ/IGI-111/empty-loops
Allow empty loops
2 parents e7403f9 + 5523faf commit 18feb76

14 files changed

Lines changed: 66 additions & 42 deletions

File tree

compiler/passes/src/loop_unrolling/ast.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
use leo_ast::{Expression::Literal, interpreter_value::literal_to_value, *};
1818

19-
use leo_errors::LoopUnrollerError;
20-
2119
use super::UnrollingVisitor;
2220

2321
impl AstReconstructor for UnrollingVisitor<'_> {
@@ -107,14 +105,19 @@ impl AstReconstructor for UnrollingVisitor<'_> {
107105
let stop_value =
108106
literal_to_value(&resolved_stop_lit, &None).expect("Parsing and type checking guarantee this works.");
109107

110-
// Ensure loop bounds are strictly increasing
111-
if start_value.gte(&stop_value).expect("Type checking guarantees these are the same type") {
112-
self.emit_err(LoopUnrollerError::loop_range_decreasing(input.stop.span()));
113-
}
114-
115108
self.loop_unrolled = true;
116109

117110
// Actually unroll.
118-
(self.unroll_iteration_statement(input, start_value, stop_value), Default::default())
111+
(
112+
if start_value.gte(&stop_value).expect("Type checking guarantees these are the same type") {
113+
let new_block_id = self.state.node_builder.next_id();
114+
self.in_scope(new_block_id, |_| {
115+
Statement::from(Block { span: input.span, statements: vec![], id: new_block_id })
116+
})
117+
} else {
118+
self.unroll_iteration_statement(input, start_value, stop_value)
119+
},
120+
Default::default(),
121+
)
119122
}
120123
}

compiler/passes/src/loop_unrolling/visitor.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ impl UnrollingVisitor<'_> {
5050
result
5151
}
5252

53-
/// Emits a Loop Unrolling Error
54-
pub fn emit_err(&self, err: LoopUnrollerError) {
55-
self.state.handler.emit_err(err);
56-
}
57-
5853
/// Unrolls an IterationStatement.
5954
pub fn unroll_iteration_statement(&mut self, input: IterationStatement, start: Value, stop: Value) -> Statement {
6055
// We already know these are integers since loop unrolling occurs after type checking.

compiler/passes/src/static_analysis/visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl StaticAnalyzingVisitor<'_> {
3939

4040
/// Emits a type checker warning
4141
pub fn emit_warning(&self, warning: StaticAnalyzerWarning) {
42-
self.state.handler.emit_warning(warning.into());
42+
self.state.handler.emit_warning(warning);
4343
}
4444

4545
/// Type checks the awaiting of a future.

compiler/passes/src/symbol_table_creation/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use leo_ast::{
3535
Type,
3636
Variant,
3737
};
38-
use leo_errors::{LeoError, Result};
38+
use leo_errors::Result;
3939
use leo_span::{Span, Symbol};
4040

4141
use indexmap::IndexMap;
@@ -146,7 +146,7 @@ impl ProgramVisitor for SymbolTableCreationVisitor<'_> {
146146
if !input.is_record {
147147
if let Some(prev_span) = self.structs.get(&full_name) {
148148
// The struct already existed
149-
return self.state.handler.emit_err::<LeoError>(SymbolTable::emit_shadow_error(
149+
return self.state.handler.emit_err(SymbolTable::emit_shadow_error(
150150
input.identifier.name,
151151
input.identifier.span,
152152
*prev_span,

compiler/passes/src/type_checking/visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl TypeCheckingVisitor<'_> {
8080
/// Emits a type checker warning
8181
pub fn emit_warning(&mut self, warning: TypeCheckerWarning) {
8282
if self.state.warnings.insert(warning.clone().into()) {
83-
self.state.handler.emit_warning(warning.into());
83+
self.state.handler.emit_warning(warning);
8484
}
8585
}
8686

errors/src/emitter/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,17 +187,17 @@ impl Handler {
187187
}
188188

189189
/// Emit the error `err`.
190-
pub fn emit_err<E: Into<LeoError>>(&self, err: E) {
190+
pub fn emit_err(&self, err: impl Into<LeoError>) {
191191
let mut inner = self.inner.borrow_mut();
192192
inner.err_count = inner.err_count.saturating_add(1);
193193
inner.emitter.emit_err(err.into());
194194
}
195195

196196
/// Emit the error `err`.
197-
pub fn emit_warning(&self, warning: LeoWarning) {
197+
pub fn emit_warning(&self, warning: impl Into<LeoWarning>) {
198198
let mut inner = self.inner.borrow_mut();
199199
inner.warn_count = inner.warn_count.saturating_add(1);
200-
inner.emitter.emit_warning(warning);
200+
inner.emitter.emit_warning(warning.into());
201201
}
202202

203203
/// The number of errors thus far.

errors/src/errors/loop_unroller/loop_unroller_errors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ create_messages!(
2323
code_mask: 9000i32,
2424
code_prefix: "LUN",
2525

26+
// TODO This error is unused. Remove it in a future version.
2627
@formatted
2728
loop_range_decreasing {
2829
args: (),
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
Error [ELUN0379000]: The loop range must be increasing.
2-
--> compiler-test:5:26
3-
|
4-
5 | const STOP: u8 = 0u8;
5-
| ^^^
1+
program test.aleo;
2+
3+
function foo:
4+
input r0 as u8.private;
5+
input r1 as u8.private;
6+
input r2 as boolean.private;
7+
output 1u8 as u8.private;

tests/expectations/compiler/statements/loop_decreasing_fail.out

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
program test.aleo;
2+
3+
function main:
4+
input r0 as u32.private;
5+
output true as boolean.private;

0 commit comments

Comments
 (0)