From ce34fbd19702b71426563a589235a2c5a1efb265 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Thu, 5 Sep 2024 16:39:38 -0400 Subject: [PATCH] fix(frontend): Ban type vars bound to a reference from passing the unconstrained boundary (#5949) # Description ## Problem\* Resolves Quick fix found while searching for other bugs ## Summary\* I have provided an example test which would previously panic during ACIR gen about all references not being resolved. However, we should have been allowing the code in the first place as it was attempting to pass a mutable reference from the constrained boundary to the unconstrained boundary. ## Additional Context ## Documentation\* Check one: - [X] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[For Experimental Features]** 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. --- compiler/noirc_frontend/src/hir_def/types.rs | 10 +++++-- compiler/noirc_frontend/src/tests.rs | 29 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 113a4fb3888..d47e6522756 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1099,13 +1099,19 @@ impl Type { | Type::Unit | Type::Constant(_) | Type::Slice(_) - | Type::TypeVariable(_, _) - | Type::NamedGeneric(_, _, _) | Type::Function(_, _, _, _) | Type::FmtString(_, _) | Type::InfixExpr(..) | Type::Error => true, + Type::TypeVariable(type_var, _) | Type::NamedGeneric(type_var, _, _) => { + if let TypeBinding::Bound(typ) = &*type_var.borrow() { + typ.is_valid_for_unconstrained_boundary() + } else { + true + } + } + // Quoted objects only exist at compile-time where the only execution // environment is the interpreter. In this environment, they are valid. Type::Quoted(_) => true, diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 04c4e414858..7160bee4931 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -3424,3 +3424,32 @@ fn errors_on_unused_function() { assert_eq!(ident.to_string(), "foo"); assert_eq!(*item_type, "function"); } + +#[test] +fn constrained_reference_to_unconstrained() { + let src = r#" + fn main(mut x: u32, y: pub u32) { + let x_ref = &mut x; + if x == 5 { + unsafe { + mut_ref_input(x_ref, y); + } + } + + assert(x == 10); + } + + unconstrained fn mut_ref_input(x: &mut u32, y: u32) { + *x = y; + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::TypeError(TypeCheckError::ConstrainedReferenceToUnconstrained { .. }) = + &errors[0].0 + else { + panic!("Expected an error about passing a constrained reference to unconstrained"); + }; +}