diff --git a/crates/noirc_errors/src/reporter.rs b/crates/noirc_errors/src/reporter.rs index 23b6970a913..6a595e5d4f6 100644 --- a/crates/noirc_errors/src/reporter.rs +++ b/crates/noirc_errors/src/reporter.rs @@ -75,7 +75,7 @@ impl CustomDiagnostic { matches!(self.kind, DiagnosticKind::Error) } - pub fn is_warrning(&self) -> bool { + pub fn is_warning(&self) -> bool { matches!(self.kind, DiagnosticKind::Warning) } } diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index efa4e694cdc..0c95af77a5a 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -1468,16 +1468,33 @@ mod test { { vecmap(programs, move |program| { let message = format!("Failed to parse:\n{}", program); - let (op_t, errors) = parse_recover(&parser, program); - for e in errors { - if !e.is_warrning() { - panic!("{}", &message); + let (op_t, diagnostics) = parse_recover(&parser, program); + diagnostics.iter().for_each(|diagnostic| { + if diagnostic.is_error() { + panic!("{} with error {}", &message, diagnostic); } - } + }); op_t.expect(&message) }) } + fn parse_all_warnings(parser: P, programs: Vec<&str>) -> Vec + where + P: NoirParser, + T: std::fmt::Display, + { + programs + .into_iter() + .flat_map(|program| { + let (_expr, diagnostics) = parse_recover(&parser, program); + diagnostics.iter().for_each(|diagnostic| if diagnostic.is_error() { + unreachable!("Expected this input to pass with warning:\n{program}\nYet it failed with error:\n{diagnostic}") + }); + diagnostics + }) + .collect() + } + fn parse_all_failing(parser: P, programs: Vec<&str>) -> Vec where P: NoirParser, @@ -1486,11 +1503,21 @@ mod test { programs .into_iter() .flat_map(|program| match parse_with(&parser, program) { - Ok(expr) => unreachable!( - "Expected this input to fail:\n{}\nYet it successfully parsed as:\n{}", - program, expr - ), - Err(error) => error, + Ok(expr) => { + unreachable!( + "Expected this input to fail:\n{}\nYet it successfully parsed as:\n{}", + program, expr + ) + } + Err(diagnostics) => { + if diagnostics.iter().all(|diagnostic: &CustomDiagnostic| diagnostic.is_warning()) { + unreachable!( + "Expected at least one error when parsing:\n{}\nYet it successfully parsed without errors:\n", + program + ) + }; + diagnostics + } }) .collect() } @@ -1679,7 +1706,7 @@ mod test { // The first (inner) `==` is a predicate which returns 0/1 // The outer layer is an infix `==` which is // associated with the Constrain statement - let errors = parse_all_failing( + let errors = parse_all_warnings( constrain(expression()), vec![ "constrain ((x + y) == k) + z == y", @@ -1690,7 +1717,9 @@ mod test { ], ); assert_eq!(errors.len(), 5); - assert!(errors.iter().all(|err| { format!("{}", err).contains("deprecated") })); + assert!(errors + .iter() + .all(|err| { err.is_warning() && format!("{}", err).contains("deprecated") })) } /// This is the standard way to declare an assert statement @@ -1784,6 +1813,8 @@ mod test { "fn f(f: pub Field, y : Field, z : comptime Field) -> u8 { x + a }", "fn f(f: pub Field, y : T, z : comptime Field) -> u8 { x + a }", "fn func_name(f: Field, y : T) where T: SomeTrait {}", + // The following should produce compile error on later stage. From the parser's perspective it's fine + "fn func_name(f: Field, y : Field, z : Field) where T: SomeTrait {}", ], ); @@ -1798,9 +1829,6 @@ mod test { "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) where SomeTrait {}", "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) SomeTrait {}", "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) where T: SomeTrait {}", - // TODO(GenericParameterNotFoundInFunction) - // Consider making this a compilation error: - // "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) where T: SomeTrait {}", ], ); } @@ -1820,6 +1848,9 @@ mod test { "trait TraitWithAssociatedType { type Element; fn item(self, index: Field) -> Self::Element; }", "trait TraitWithAssociatedConstant { let Size: Field; }", "trait TraitWithAssociatedConstantWithDefaultValue { let Size: Field = 10; }", + "trait GenericTrait { fn elem(&mut self, index: Field) -> T; }", + "trait GenericTraitWithConstraints where T: SomeTrait { fn elem(self, index: Field) -> T; }", + "trait TraitWithMultipleGenericParams where A: SomeTrait, B: AnotherTrait { let Size: Field; fn zero() -> Self; }", ], ); @@ -1829,11 +1860,6 @@ mod test { "trait MissingBody", "trait WrongDelimiter { fn foo() -> u8, fn bar() -> u8 }", "trait WhereClauseWithoutGenerics where A: SomeTrait { }", - // TODO: when implemnt generics in traits the following 3 should pass - "trait GenericTrait { fn elem(&mut self, index: Field) -> T; }", - "trait GenericTraitWithConstraints where T: SomeTrait { fn elem(self, index: Field) -> T; }", - "trait TraitWithMultipleGenericParams where A: SomeTrait, B: AnotherTrait { comptime Size: Field; fn zero() -> Self; }", - ], ); }