Skip to content

Commit

Permalink
fix: added error messages for passing oracles and references from unc…
Browse files Browse the repository at this point in the history
…onstrained to constrained functions (#4570)

# Description
Added compiler errors for when a oracle or reference is passed from a
unconstrained to a constrained function.

## Problem\*
Currently the compiler panics when you pass a reference or an oracle
from a unconstrained to constrained function.

Resolves #4565

Closes 4565

## Summary\*
A compiler error has been added for each condition with an appropriate
message to aid the user.

## Documentation\*

Check one:
- [X ] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[Exceptional Case]** Documentation to be submitted in a separate
PR.

# PR Checklist\*

- [ X] I have tested the changes locally.
- [ X] I have formatted the changes with
[Prettier](https://prettier.io/) and/or `cargo fmt` on default settings.

---------

Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>
  • Loading branch information
Andy53 and vezenovm committed Mar 18, 2024
1 parent dfa5126 commit 265bd8b
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 11 deletions.
3 changes: 3 additions & 0 deletions compiler/noirc_evaluator/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ pub enum RuntimeError {
BigIntModulus { call_stack: CallStack },
#[error("Slices cannot be returned from an unconstrained runtime to a constrained runtime")]
UnconstrainedSliceReturnToConstrained { call_stack: CallStack },
#[error("All `oracle` methods should be wrapped in an unconstrained fn")]
UnconstrainedOracleReturnToConstrained { call_stack: CallStack },
}

// We avoid showing the actual lhs and rhs since most of the time they are just 0
Expand Down Expand Up @@ -139,6 +141,7 @@ impl RuntimeError {
| RuntimeError::NestedSlice { call_stack, .. }
| RuntimeError::BigIntModulus { call_stack, .. }
| RuntimeError::UnconstrainedSliceReturnToConstrained { call_stack } => call_stack,
RuntimeError::UnconstrainedOracleReturnToConstrained { call_stack } => call_stack,
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,9 +612,11 @@ impl Context {
self.ssa_values.insert(*result, output);
}
}
Value::ForeignFunction(_) => unreachable!(
"All `oracle` methods should be wrapped in an unconstrained fn"
),
Value::ForeignFunction(_) => {
return Err(RuntimeError::UnconstrainedOracleReturnToConstrained {
call_stack: self.acir_context.get_call_stack(),
})
}
_ => unreachable!("expected calling a function but got {function_value:?}"),
}
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/noirc_frontend/src/hir/type_check/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ pub enum TypeCheckError {
"Cannot pass a mutable reference from a constrained runtime to an unconstrained runtime"
)]
ConstrainedReferenceToUnconstrained { span: Span },
#[error(
"Cannot pass a mutable reference from a unconstrained runtime to an constrained runtime"
)]
UnconstrainedReferenceToConstrained { span: Span },
#[error("Slices cannot be returned from an unconstrained runtime to a constrained runtime")]
UnconstrainedSliceReturnToConstrained { span: Span },
#[error("Only sized types may be used in the entry point to a program")]
Expand Down Expand Up @@ -229,6 +233,7 @@ impl From<TypeCheckError> for Diagnostic {
| TypeCheckError::OverflowingAssignment { span, .. }
| TypeCheckError::FieldModulo { span }
| TypeCheckError::ConstrainedReferenceToUnconstrained { span }
| TypeCheckError::UnconstrainedReferenceToConstrained { span }
| TypeCheckError::UnconstrainedSliceReturnToConstrained { span } => {
Diagnostic::simple_error(error.to_string(), String::new(), span)
}
Expand Down
20 changes: 12 additions & 8 deletions compiler/noirc_frontend/src/hir/type_check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,18 @@ impl<'interner> TypeChecker<'interner> {
let return_type = self.bind_function_type(function, args, span);

// Check that we are not passing a slice from an unconstrained runtime to a constrained runtime
if is_current_func_constrained
&& is_unconstrained_call
&& return_type.contains_slice()
{
self.errors.push(TypeCheckError::UnconstrainedSliceReturnToConstrained {
span: self.interner.expr_span(expr_id),
});
return Type::Error;
if is_current_func_constrained && is_unconstrained_call {
if return_type.contains_slice() {
self.errors.push(TypeCheckError::UnconstrainedSliceReturnToConstrained {
span: self.interner.expr_span(expr_id),
});
return Type::Error;
} else if matches!(&return_type.follow_bindings(), Type::MutableReference(_)) {
self.errors.push(TypeCheckError::UnconstrainedReferenceToConstrained {
span: self.interner.expr_span(expr_id),
});
return Type::Error;
}
}

return_type
Expand Down
5 changes: 5 additions & 0 deletions test_programs/compile_failure/unconstrained_oracle/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
name = "unconstrained_oracle"
type = "bin"
authors = [""]
[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[oracle(getNoun)]
unconstrained fn external_fn() -> Field {
100 / 5
}

fn main() {
let x = anon();
assert(x * 5 == 100);
}
5 changes: 5 additions & 0 deletions test_programs/compile_failure/unconstrained_ref/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
name = "unconstrained_ref"
type = "bin"
authors = [""]
[dependencies]
8 changes: 8 additions & 0 deletions test_programs/compile_failure/unconstrained_ref/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
unconstrained fn uncon_ref() -> &mut Field {
let lr = &mut 7;
lr
}

fn main() {
let e = uncon_ref();
}

0 comments on commit 265bd8b

Please sign in to comment.