Skip to content

Commit

Permalink
Merge 949274c into e3cdebe
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Sep 24, 2024
2 parents e3cdebe + 949274c commit 8f713e9
Show file tree
Hide file tree
Showing 8 changed files with 731 additions and 715 deletions.
718 changes: 5 additions & 713 deletions compiler/noirc_frontend/src/tests.rs

Large diffs are not rendered by default.

79 changes: 79 additions & 0 deletions compiler/noirc_frontend/src/tests/bound_checks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use crate::hir::def_collector::dc_crate::CompilationError;

use super::get_program_errors;

#[test]
fn overflowing_u8() {
let src = r#"
fn main() {
let _: u8 = 256;
}"#;
let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

if let CompilationError::TypeError(error) = &errors[0].0 {
assert_eq!(
error.to_string(),
"The value `2⁸` cannot fit into `u8` which has range `0..=255`"
);
} else {
panic!("Expected OverflowingAssignment error, got {:?}", errors[0].0);
}
}

#[test]
fn underflowing_u8() {
let src = r#"
fn main() {
let _: u8 = -1;
}"#;
let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

if let CompilationError::TypeError(error) = &errors[0].0 {
assert_eq!(
error.to_string(),
"The value `-1` cannot fit into `u8` which has range `0..=255`"
);
} else {
panic!("Expected OverflowingAssignment error, got {:?}", errors[0].0);
}
}

#[test]
fn overflowing_i8() {
let src = r#"
fn main() {
let _: i8 = 128;
}"#;
let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

if let CompilationError::TypeError(error) = &errors[0].0 {
assert_eq!(
error.to_string(),
"The value `2⁷` cannot fit into `i8` which has range `-128..=127`"
);
} else {
panic!("Expected OverflowingAssignment error, got {:?}", errors[0].0);
}
}

#[test]
fn underflowing_i8() {
let src = r#"
fn main() {
let _: i8 = -129;
}"#;
let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

if let CompilationError::TypeError(error) = &errors[0].0 {
assert_eq!(
error.to_string(),
"The value `-129` cannot fit into `i8` which has range `-128..=127`"
);
} else {
panic!("Expected OverflowingAssignment error, got {:?}", errors[0].0);
}
}
112 changes: 112 additions & 0 deletions compiler/noirc_frontend/src/tests/imports.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use crate::hir::{
def_collector::{dc_crate::CompilationError, errors::DefCollectorErrorKind},
resolution::{errors::ResolverError, import::PathResolutionError},
};

use super::{assert_no_errors, get_program_errors};

#[test]
fn use_super() {
let src = r#"
fn some_func() {}
mod foo {
use super::some_func;
pub fn bar() {
some_func();
}
}
"#;
assert_no_errors(src);
}

#[test]
fn use_super_in_path() {
let src = r#"
fn some_func() {}
mod foo {
pub fn func() {
super::some_func();
}
}
"#;
assert_no_errors(src);
}

#[test]
fn warns_on_use_of_private_exported_item() {
let src = r#"
mod foo {
mod bar {
pub fn baz() {}
}
use bar::baz;
pub fn qux() {
baz();
}
}
fn main() {
foo::baz();
}
"#;

let errors = get_program_errors(src);
assert_eq!(errors.len(), 2); // An existing bug causes this error to be duplicated

assert!(matches!(
&errors[0].0,
CompilationError::ResolverError(ResolverError::PathResolutionError(
PathResolutionError::Private(..),
))
));
}

#[test]
fn can_use_pub_use_item() {
let src = r#"
mod foo {
mod bar {
pub fn baz() {}
}
pub use bar::baz;
}
fn main() {
foo::baz();
}
"#;
assert_no_errors(src);
}

#[test]
fn warns_on_re_export_of_item_with_less_visibility() {
let src = r#"
mod foo {
mod bar {
pub(crate) fn baz() {}
}
pub use bar::baz;
}
fn main() {
foo::baz();
}
"#;

let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

assert!(matches!(
&errors[0].0,
CompilationError::DefinitionError(
DefCollectorErrorKind::CannotReexportItemWithLessVisibility { .. }
)
));
}
65 changes: 65 additions & 0 deletions compiler/noirc_frontend/src/tests/metaprogramming.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use crate::hir::def_collector::dc_crate::CompilationError;

use super::get_program_errors;

#[test]
fn comptime_type_in_runtime_code() {
let source = "pub fn foo(_f: FunctionDefinition) {}";
let errors = get_program_errors(source);
assert_eq!(errors.len(), 1);
assert!(matches!(
errors[0].0,
CompilationError::ResolverError(ResolverError::ComptimeTypeInRuntimeCode { .. })
));
}

#[test]
fn macro_result_type_mismatch() {
let src = r#"
fn main() {
comptime {
let x = unquote!(quote { "test" });
let _: Field = x;
}
}
comptime fn unquote(q: Quoted) -> Quoted {
q
}
"#;

let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);
assert!(matches!(
errors[0].0,
CompilationError::TypeError(TypeCheckError::TypeMismatch { .. })
));
}

#[test]
fn unquoted_integer_as_integer_token() {
let src = r#"
trait Serialize<let N: u32> {
fn serialize() {}
}
#[attr]
pub fn foobar() {}
comptime fn attr(_f: FunctionDefinition) -> Quoted {
let serialized_len = 1;
// We are testing that when we unquote $serialized_len, it's unquoted
// as the token `1` and not as something else that later won't be parsed correctly
// in the context of a generic argument.
quote {
impl Serialize<$serialized_len> for Field {
fn serialize() { }
}
}
}
fn main() {}
"#;

assert_no_errors(src);
}
111 changes: 111 additions & 0 deletions compiler/noirc_frontend/src/tests/references.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use crate::hir::{
def_collector::dc_crate::CompilationError, resolution::errors::ResolverError,
type_check::TypeCheckError,
};

use super::get_program_errors;

#[test]
fn cannot_mutate_immutable_variable() {
let src = r#"
fn main() {
let array = [1];
mutate(&mut array);
}
fn mutate(_: &mut [Field; 1]) {}
"#;

let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

let CompilationError::TypeError(TypeCheckError::CannotMutateImmutableVariable { name, .. }) =
&errors[0].0
else {
panic!("Expected a CannotMutateImmutableVariable error");
};

assert_eq!(name, "array");
}

#[test]
fn cannot_mutate_immutable_variable_on_member_access() {
let src = r#"
struct Foo {
x: Field
}
fn main() {
let foo = Foo { x: 0 };
mutate(&mut foo.x);
}
fn mutate(foo: &mut Field) {
*foo = 1;
}
"#;

let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

let CompilationError::TypeError(TypeCheckError::CannotMutateImmutableVariable { name, .. }) =
&errors[0].0
else {
panic!("Expected a CannotMutateImmutableVariable error");
};

assert_eq!(name, "foo");
}

#[test]
fn does_not_crash_when_passing_mutable_undefined_variable() {
let src = r#"
fn main() {
mutate(&mut undefined);
}
fn mutate(foo: &mut Field) {
*foo = 1;
}
"#;

let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

let CompilationError::ResolverError(ResolverError::VariableNotDeclared { name, .. }) =
&errors[0].0
else {
panic!("Expected a VariableNotDeclared error");
};

assert_eq!(name, "undefined");
}

#[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");
};
}
Loading

0 comments on commit 8f713e9

Please sign in to comment.