Skip to content

Commit

Permalink
feat: Make for-loop range be a polymorphic integer instead of just Fi…
Browse files Browse the repository at this point in the history
…eld in unconstrained functions (#1583)

* make ranges be polymorphic integers

* make behavior consistent

* remove closure

* change index_type

* Update crates/noirc_frontend/src/hir/type_check/expr.rs

---------

Co-authored-by: jfecher <jake@aztecprotocol.com>
  • Loading branch information
kevaundray and jfecher authored Jun 8, 2023
1 parent 537d33d commit 77fba56
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 18 deletions.
3 changes: 2 additions & 1 deletion crates/noirc_evaluator/src/ssa_refactor/ssa_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ impl<'a> FunctionContext<'a> {
let loop_end = self.builder.insert_block();

// this is the 'i' in `for i in start .. end { block }`
let loop_index = self.builder.add_block_parameter(loop_entry, Type::field());
let index_type = Self::convert_non_tuple_type(&for_expr.index_type);
let loop_index = self.builder.add_block_parameter(loop_entry, index_type);

let start_index = self.codegen_non_tuple_expression(&for_expr.start_range);
let end_index = self.codegen_non_tuple_expression(&for_expr.end_range);
Expand Down
42 changes: 25 additions & 17 deletions crates/noirc_frontend/src/hir/type_check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,25 +153,33 @@ impl<'interner> TypeChecker<'interner> {
let start_span = self.interner.expr_span(&for_expr.start_range);
let end_span = self.interner.expr_span(&for_expr.end_range);

let mut unify_loop_range = |actual_type, span| {
let expected_type = if self.is_unconstrained() {
Type::FieldElement(CompTime::new(self.interner))
} else {
Type::comp_time(Some(span))
};
// Check that start range and end range have the same types
let range_span = start_span.merge(end_span);
self.unify(&start_range_type, &end_range_type, range_span, || {
TypeCheckError::TypeMismatch {
expected_typ: start_range_type.to_string(),
expr_typ: end_range_type.to_string(),
expr_span: range_span,
}
});

self.unify(actual_type, &expected_type, span, || {
TypeCheckError::TypeCannotBeUsed {
typ: start_range_type.clone(),
place: "for loop",
span,
}
.add_context("The range of a loop must be known at compile-time")
});
let expected_comptime = if self.is_unconstrained() {
CompTime::new(self.interner)
} else {
CompTime::Yes(Some(range_span))
};

unify_loop_range(&start_range_type, start_span);
unify_loop_range(&end_range_type, end_span);
let fresh_id = self.interner.next_type_variable_id();
let type_variable = Shared::new(TypeBinding::Unbound(fresh_id));
let expected_type = Type::PolymorphicInteger(expected_comptime, type_variable);

self.unify(&start_range_type, &expected_type, range_span, || {
TypeCheckError::TypeCannotBeUsed {
typ: start_range_type.clone(),
place: "for loop",
span: range_span,
}
.add_context("The range of a loop must be known at compile-time")
});

self.interner.push_definition_type(for_expr.identifier.id, start_range_type);

Expand Down

0 comments on commit 77fba56

Please sign in to comment.