From b43dcb2b30ce090c393990b2192411f9b3dc6a9e Mon Sep 17 00:00:00 2001 From: jfecher Date: Tue, 8 Oct 2024 11:49:17 +0100 Subject: [PATCH] fix!: Change tag attributes to require a ' prefix (#6235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description ## Problem\* ## Summary\* Changes tag attributes (previously Custom attributes) to require a `'` prefix. This distinguishes them from the more common Meta attributes which are expected to call a metaprogramming function. The program: ```rs #[not_in_scope] fn main() {} ``` Now errors with: ``` error: Attribute function `not_in_scope` is not in scope ┌─ src/main.nr:1:3 │ 1 │ #[not_in_scope] │ ------------ │ ``` ## Additional Context - It turns out the `#[deprecated = ...]` attribute was not being handled previously. I'm not sure if this was expected but it's now easier to see now that we get an error if it does not get a `'` prefix. - This also pointed out that `derive` was not working within the stdlib in the `meta/ops.nr` file. `derive` was never imported there. Moreover, after being used we get errors since derive tries to insert `std::cmp::Ordering` paths which are invalid within the stdlib where they should be `crate::cmp::Ordering` instead. So I replaced these calls with explicit impls. ## Documentation\* Check one: - [x] No documentation needed. - We may possibly need to document Tag attributes, but I'm unsure who the user would be. - [ ] 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_driver/src/lib.rs | 2 +- compiler/noirc_frontend/src/ast/visitor.rs | 2 +- .../noirc_frontend/src/elaborator/comptime.rs | 36 ++++++++++++++----- .../src/hir/comptime/interpreter/builtin.rs | 2 +- .../src/hir/resolution/errors.rs | 27 ++++++++++++++ compiler/noirc_frontend/src/lexer/lexer.rs | 19 ++++++---- compiler/noirc_frontend/src/lexer/token.rs | 30 ++++++++++++---- .../src/parser/parser/attributes.rs | 6 ++-- compiler/noirc_frontend/src/tests.rs | 16 +++++++++ noir_stdlib/src/ec/consts/te.nr | 3 +- noir_stdlib/src/hash/mimc.nr | 6 ++-- noir_stdlib/src/meta/mod.nr | 2 ++ noir_stdlib/src/meta/op.nr | 29 +++++++++++++-- noir_stdlib/src/sha256.nr | 4 +-- noir_stdlib/src/sha512.nr | 2 +- .../attributes_multiple/src/main.nr | 4 +-- .../attributes_struct/src/main.nr | 4 +-- .../comptime_module/src/main.nr | 6 ++-- .../inline_never_basic/Nargo.toml | 7 ---- .../inline_never_basic/Prover.toml | 2 -- .../inline_never_basic/src/main.nr | 8 ----- tooling/nargo_fmt/src/visitor/item.rs | 9 +++-- 22 files changed, 164 insertions(+), 62 deletions(-) delete mode 100644 test_programs/execution_success/inline_never_basic/Nargo.toml delete mode 100644 test_programs/execution_success/inline_never_basic/Prover.toml delete mode 100644 test_programs/execution_success/inline_never_basic/src/main.nr diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 1d69e435738..2f0122524eb 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -445,7 +445,7 @@ fn compile_contract_inner( .secondary .iter() .filter_map(|attr| { - if let SecondaryAttribute::Custom(attribute) = attr { + if let SecondaryAttribute::Tag(attribute) = attr { Some(&attribute.contents) } else { None diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index 6e3e830e3f9..632c5656137 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -1391,7 +1391,7 @@ impl SecondaryAttribute { } pub fn accept_children(&self, target: AttributeTarget, visitor: &mut impl Visitor) { - if let SecondaryAttribute::Custom(custom) = self { + if let SecondaryAttribute::Meta(custom) = self { custom.accept(target, visitor); } } diff --git a/compiler/noirc_frontend/src/elaborator/comptime.rs b/compiler/noirc_frontend/src/elaborator/comptime.rs index 426e160206f..65cb6072c62 100644 --- a/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -158,7 +158,7 @@ impl<'context> Elaborator<'context> { attribute_context: AttributeContext, generated_items: &mut CollectedItems, ) { - if let SecondaryAttribute::Custom(attribute) = attribute { + if let SecondaryAttribute::Meta(attribute) = attribute { self.elaborate_in_comptime_context(|this| { if let Err(error) = this.run_comptime_attribute_name_on_item( &attribute.contents, @@ -188,25 +188,45 @@ impl<'context> Elaborator<'context> { let location = Location::new(attribute_span, self.file); let Some((function, arguments)) = Self::parse_attribute(attribute, location)? else { - // Do not issue an error if the attribute is unknown - return Ok(()); + return Err(( + ResolverError::UnableToParseAttribute { + attribute: attribute.to_string(), + span: attribute_span, + } + .into(), + self.file, + )); }; // Elaborate the function, rolling back any errors generated in case it is unknown let error_count = self.errors.len(); + let function_string = function.to_string(); let function = self.elaborate_expression(function).0; self.errors.truncate(error_count); let definition_id = match self.interner.expression(&function) { HirExpression::Ident(ident, _) => ident.id, - _ => return Ok(()), + _ => { + return Err(( + ResolverError::AttributeFunctionIsNotAPath { + function: function_string, + span: attribute_span, + } + .into(), + self.file, + )) + } }; let Some(definition) = self.interner.try_definition(definition_id) else { - // If there's no such function, don't return an error. - // This preserves backwards compatibility in allowing custom attributes that - // do not refer to comptime functions. - return Ok(()); + return Err(( + ResolverError::AttributeFunctionNotInScope { + name: function_string, + span: attribute_span, + } + .into(), + self.file, + )); }; let DefinitionKind::Function(function) = definition.kind else { diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index c80dbb480f5..9f44de29ea1 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -2242,7 +2242,7 @@ fn function_def_add_attribute( } } - if let Attribute::Secondary(SecondaryAttribute::Custom(attribute)) = attribute { + if let Attribute::Secondary(SecondaryAttribute::Tag(attribute)) = attribute { let func_meta = interpreter.elaborator.interner.function_meta_mut(&func_id); func_meta.custom_attributes.push(attribute); } diff --git a/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs index 4e9520ad761..e3f3d488c43 100644 --- a/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -138,6 +138,12 @@ pub enum ResolverError { UnsupportedNumericGenericType(#[from] UnsupportedNumericGenericType), #[error("Type `{typ}` is more private than item `{item}`")] TypeIsMorePrivateThenItem { typ: String, item: String, span: Span }, + #[error("Unable to parse attribute `{attribute}`")] + UnableToParseAttribute { attribute: String, span: Span }, + #[error("Attribute function `{function}` is not a path")] + AttributeFunctionIsNotAPath { function: String, span: Span }, + #[error("Attribute function `{name}` is not in scope")] + AttributeFunctionNotInScope { name: String, span: Span }, } impl ResolverError { @@ -546,6 +552,27 @@ impl<'a> From<&'a ResolverError> for Diagnostic { *span, ) }, + ResolverError::UnableToParseAttribute { attribute, span } => { + Diagnostic::simple_error( + format!("Unable to parse attribute `{attribute}`"), + "Attribute should be a function or function call".into(), + *span, + ) + }, + ResolverError::AttributeFunctionIsNotAPath { function, span } => { + Diagnostic::simple_error( + format!("Attribute function `{function}` is not a path"), + "An attribute's function should be a single identifier or a path".into(), + *span, + ) + }, + ResolverError::AttributeFunctionNotInScope { name, span } => { + Diagnostic::simple_error( + format!("Attribute function `{name}` is not in scope"), + String::new(), + *span, + ) + }, } } } diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index 069487acb46..adc68351e3c 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -301,6 +301,11 @@ impl<'a> Lexer<'a> { } self.next_char(); + let is_tag = self.peek_char_is('\''); + if is_tag { + self.next_char(); + } + let contents_start = self.position + 1; let word = self.eat_while(None, |ch| ch != ']'); @@ -321,7 +326,7 @@ impl<'a> Lexer<'a> { let span = Span::inclusive(start, end); let contents_span = Span::inclusive(contents_start, contents_end); - let attribute = Attribute::lookup_attribute(&word, span, contents_span)?; + let attribute = Attribute::lookup_attribute(&word, span, contents_span, is_tag)?; if is_inner { match attribute { Attribute::Function(attribute) => Err(LexerErrorKind::InvalidInnerAttribute { @@ -838,17 +843,17 @@ mod tests { } #[test] - fn custom_attribute() { - let input = r#"#[custom(hello)]"#; + fn tag_attribute() { + let input = r#"#['custom(hello)]"#; let mut lexer = Lexer::new(input); let token = lexer.next_token().unwrap(); assert_eq!( token.token(), - &Token::Attribute(Attribute::Secondary(SecondaryAttribute::Custom(CustomAttribute { + &Token::Attribute(Attribute::Secondary(SecondaryAttribute::Tag(CustomAttribute { contents: "custom(hello)".to_string(), - span: Span::from(0..16), - contents_span: Span::from(2..15) + span: Span::from(0..17), + contents_span: Span::from(3..16) }))) ); } @@ -943,7 +948,7 @@ mod tests { let token = lexer.next_token().unwrap(); assert_eq!( token.token(), - &Token::InnerAttribute(SecondaryAttribute::Custom(CustomAttribute { + &Token::InnerAttribute(SecondaryAttribute::Meta(CustomAttribute { contents: "something".to_string(), span: Span::from(0..13), contents_span: Span::from(3..12), diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index d79a184d4c4..68d18302f34 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -738,6 +738,7 @@ impl Attribute { word: &str, span: Span, contents_span: Span, + is_tag: bool, ) -> Result { let word_segments: Vec<&str> = word .split(|c| c == '(' || c == ')') @@ -758,6 +759,14 @@ impl Attribute { is_valid.ok_or(LexerErrorKind::MalformedFuncAttribute { span, found: word.to_owned() }) }; + if is_tag { + return Ok(Attribute::Secondary(SecondaryAttribute::Tag(CustomAttribute { + contents: word.to_owned(), + span, + contents_span, + }))); + } + let attribute = match &word_segments[..] { // Primary Attributes ["foreign", name] => { @@ -813,7 +822,7 @@ impl Attribute { ["allow", tag] => Attribute::Secondary(SecondaryAttribute::Allow(tag.to_string())), tokens => { tokens.iter().try_for_each(|token| validate(token))?; - Attribute::Secondary(SecondaryAttribute::Custom(CustomAttribute { + Attribute::Secondary(SecondaryAttribute::Meta(CustomAttribute { contents: word.to_owned(), span, contents_span, @@ -922,7 +931,13 @@ pub enum SecondaryAttribute { ContractLibraryMethod, Export, Field(String), - Custom(CustomAttribute), + + /// A custom tag attribute: #['foo] + Tag(CustomAttribute), + + /// An attribute expected to run a comptime function of the same name: #[foo] + Meta(CustomAttribute), + Abi(String), /// A variable-argument comptime function. @@ -939,7 +954,7 @@ pub enum SecondaryAttribute { impl SecondaryAttribute { pub(crate) fn as_custom(&self) -> Option<&CustomAttribute> { - if let Self::Custom(attribute) = self { + if let Self::Tag(attribute) = self { Some(attribute) } else { None @@ -954,7 +969,8 @@ impl SecondaryAttribute { } SecondaryAttribute::Export => Some("export".to_string()), SecondaryAttribute::Field(_) => Some("field".to_string()), - SecondaryAttribute::Custom(custom) => custom.name(), + SecondaryAttribute::Tag(custom) => custom.name(), + SecondaryAttribute::Meta(custom) => custom.name(), SecondaryAttribute::Abi(_) => Some("abi".to_string()), SecondaryAttribute::Varargs => Some("varargs".to_string()), SecondaryAttribute::UseCallersScope => Some("use_callers_scope".to_string()), @@ -977,7 +993,8 @@ impl fmt::Display for SecondaryAttribute { SecondaryAttribute::Deprecated(Some(ref note)) => { write!(f, r#"#[deprecated("{note}")]"#) } - SecondaryAttribute::Custom(ref attribute) => write!(f, "#[{}]", attribute.contents), + SecondaryAttribute::Tag(ref attribute) => write!(f, "#['{}]", attribute.contents), + SecondaryAttribute::Meta(ref attribute) => write!(f, "#[{}]", attribute.contents), SecondaryAttribute::ContractLibraryMethod => write!(f, "#[contract_library_method]"), SecondaryAttribute::Export => write!(f, "#[export]"), SecondaryAttribute::Field(ref k) => write!(f, "#[field({k})]"), @@ -1029,7 +1046,8 @@ impl AsRef for SecondaryAttribute { match self { SecondaryAttribute::Deprecated(Some(string)) => string, SecondaryAttribute::Deprecated(None) => "", - SecondaryAttribute::Custom(attribute) => &attribute.contents, + SecondaryAttribute::Tag(attribute) => &attribute.contents, + SecondaryAttribute::Meta(attribute) => &attribute.contents, SecondaryAttribute::Field(string) | SecondaryAttribute::Abi(string) | SecondaryAttribute::Allow(string) => string, diff --git a/compiler/noirc_frontend/src/parser/parser/attributes.rs b/compiler/noirc_frontend/src/parser/parser/attributes.rs index d0f7221a6be..ffba74003b7 100644 --- a/compiler/noirc_frontend/src/parser/parser/attributes.rs +++ b/compiler/noirc_frontend/src/parser/parser/attributes.rs @@ -55,10 +55,10 @@ mod tests { #[test] fn parses_inner_attribute() { - let src = "#![hello]"; + let src = "#!['hello]"; let mut parser = Parser::for_str(src); - let Some(SecondaryAttribute::Custom(custom)) = parser.parse_inner_attribute() else { - panic!("Expected inner custom attribute"); + let Some(SecondaryAttribute::Tag(custom)) = parser.parse_inner_attribute() else { + panic!("Expected inner tag attribute"); }; expect_no_errors(&parser.errors); assert_eq!(custom.contents, "hello"); diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 65841b643c4..3d099fe09c1 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -3203,3 +3203,19 @@ fn trait_unconstrained_methods_typechecked_correctly() { println!("{errors:?}"); assert_eq!(errors.len(), 0); } + +#[test] +fn error_if_attribute_not_in_scope() { + let src = r#" + #[not_in_scope] + fn main() {} + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::AttributeFunctionNotInScope { .. }) + )); +} diff --git a/noir_stdlib/src/ec/consts/te.nr b/noir_stdlib/src/ec/consts/te.nr index e82302eadee..8c49226071f 100644 --- a/noir_stdlib/src/ec/consts/te.nr +++ b/noir_stdlib/src/ec/consts/te.nr @@ -8,7 +8,8 @@ pub struct BabyJubjub { } #[field(bn254)] -#[deprecated = "It's recommmended to use the external noir-edwards library (https://github.com/noir-lang/noir-edwards)"] +// Uncommenting this results in deprecated warnings in the stdlib +// #[deprecated] pub fn baby_jubjub() -> BabyJubjub { BabyJubjub { // Baby Jubjub (ERC-2494) parameters in affine representation diff --git a/noir_stdlib/src/hash/mimc.nr b/noir_stdlib/src/hash/mimc.nr index 1bcc9e3fcc7..84ee177b663 100644 --- a/noir_stdlib/src/hash/mimc.nr +++ b/noir_stdlib/src/hash/mimc.nr @@ -6,7 +6,9 @@ use crate::default::Default; // You must use constants generated for the native field // Rounds number should be ~ log(p)/log(exp) // For 254 bit primes, exponent 7 and 91 rounds seems to be recommended -#[deprecated = "It's recommmended to use the external MiMC library (https://github.com/noir-lang/mimc)"] +// +// Uncommenting this results in deprecated warnings in the stdlib +// #[deprecated] fn mimc(x: Field, k: Field, constants: [Field; N], exp: Field) -> Field { //round 0 let mut t = x + k; @@ -117,7 +119,7 @@ global MIMC_BN254_CONSTANTS: [Field; MIMC_BN254_ROUNDS] = [ //mimc implementation with hardcoded parameters for BN254 curve. #[field(bn254)] -#[deprecated = "It's recommmended to use the external MiMC library (https://github.com/noir-lang/mimc)"] +#[deprecated] pub fn mimc_bn254(array: [Field; N]) -> Field { let exponent = 7; let mut r = 0; diff --git a/noir_stdlib/src/meta/mod.nr b/noir_stdlib/src/meta/mod.nr index 378f0df1ba8..f756be364b1 100644 --- a/noir_stdlib/src/meta/mod.nr +++ b/noir_stdlib/src/meta/mod.nr @@ -118,6 +118,8 @@ pub comptime fn make_trait_impl( } mod tests { + use crate::meta::derive_via; + // docs:start:quote-example comptime fn quote_one() -> Quoted { quote { 1 } diff --git a/noir_stdlib/src/meta/op.nr b/noir_stdlib/src/meta/op.nr index 197daaabaa6..39ec918fe39 100644 --- a/noir_stdlib/src/meta/op.nr +++ b/noir_stdlib/src/meta/op.nr @@ -1,8 +1,22 @@ -#[derive(Eq, Hash)] pub struct UnaryOp { op: Field } +// Cannot derive Eq or Hash since they internally use paths +// starting with std:: which is invalid within the same crate. +// We'd need to use crate:: instead. +impl crate::cmp::Eq for UnaryOp { + fn eq(self, other: Self) -> bool { + self.op == other.op + } +} + +impl crate::hash::Hash for UnaryOp { + fn hash(self, h: &mut H) where H: crate::hash::Hasher { + self.op.hash(h); + } +} + impl UnaryOp { // docs:start:is_minus pub fn is_minus(self) -> bool { @@ -46,11 +60,22 @@ impl UnaryOp { } } -#[derive(Eq, Hash)] pub struct BinaryOp { op: Field } +impl crate::cmp::Eq for BinaryOp { + fn eq(self, other: Self) -> bool { + self.op == other.op + } +} + +impl crate::hash::Hash for BinaryOp { + fn hash(self, h: &mut H) where H: crate::hash::Hasher { + self.op.hash(h); + } +} + impl BinaryOp { // docs:start:is_add pub fn is_add(self) -> bool { diff --git a/noir_stdlib/src/sha256.nr b/noir_stdlib/src/sha256.nr index 7679e517317..39e72cfbeb8 100644 --- a/noir_stdlib/src/sha256.nr +++ b/noir_stdlib/src/sha256.nr @@ -1,11 +1,11 @@ // This file is kept for backwards compatibility. -#[deprecated = "replace with std::hash::sha256::digest"] +#[deprecated] pub fn digest(msg: [u8; N]) -> [u8; 32] { crate::hash::sha256::digest(msg) } -#[deprecated = "replace with std::hash::sha256::sha256_var"] +#[deprecated] pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { crate::hash::sha256::sha256_var(msg, message_size) } diff --git a/noir_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr index 0a8a5bf4760..c66d898b0cf 100644 --- a/noir_stdlib/src/sha512.nr +++ b/noir_stdlib/src/sha512.nr @@ -1,6 +1,6 @@ // This file is kept for backwards compatibility. -#[deprecated = "replace with std::hash::sha512::digest"] +#[deprecated] pub fn digest(msg: [u8; N]) -> [u8; 64] { crate::hash::sha512::digest(msg) } diff --git a/test_programs/compile_success_empty/attributes_multiple/src/main.nr b/test_programs/compile_success_empty/attributes_multiple/src/main.nr index 581fb989b4c..aadfe5caf3c 100644 --- a/test_programs/compile_success_empty/attributes_multiple/src/main.nr +++ b/test_programs/compile_success_empty/attributes_multiple/src/main.nr @@ -2,6 +2,6 @@ fn main() { another_func() } -#[aztec(private)] -#[internal] +#['aztec(private)] +#['internal] fn another_func() {} diff --git a/test_programs/compile_success_empty/attributes_struct/src/main.nr b/test_programs/compile_success_empty/attributes_struct/src/main.nr index 669cfc32927..5c82145b431 100644 --- a/test_programs/compile_success_empty/attributes_struct/src/main.nr +++ b/test_programs/compile_success_empty/attributes_struct/src/main.nr @@ -1,5 +1,5 @@ -#[some_attribute] -#[another_attribute] +#['some_attribute] +#['another_attribute] struct SomeStruct { a: Field, b: Field diff --git a/test_programs/compile_success_empty/comptime_module/src/main.nr b/test_programs/compile_success_empty/comptime_module/src/main.nr index 5099f3b7acb..09b1e98744d 100644 --- a/test_programs/compile_success_empty/comptime_module/src/main.nr +++ b/test_programs/compile_success_empty/comptime_module/src/main.nr @@ -1,6 +1,6 @@ -#[outer_attribute] +#['outer_attribute] mod foo { - #![some_attribute] + #!['some_attribute] pub fn x() {} pub fn y() {} pub fn z() {} @@ -12,7 +12,7 @@ mod foo { contract bar {} -#[some_attribute] +#['some_attribute] mod another_module {} #[outer_attribute_func] diff --git a/test_programs/execution_success/inline_never_basic/Nargo.toml b/test_programs/execution_success/inline_never_basic/Nargo.toml deleted file mode 100644 index 16691770d76..00000000000 --- a/test_programs/execution_success/inline_never_basic/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "inline_never_basic" -type = "bin" -authors = [""] -compiler_version = ">=0.27.0" - -[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/inline_never_basic/Prover.toml b/test_programs/execution_success/inline_never_basic/Prover.toml deleted file mode 100644 index f28f2f8cc48..00000000000 --- a/test_programs/execution_success/inline_never_basic/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "5" -y = "10" diff --git a/test_programs/execution_success/inline_never_basic/src/main.nr b/test_programs/execution_success/inline_never_basic/src/main.nr deleted file mode 100644 index 1922aaedb6c..00000000000 --- a/test_programs/execution_success/inline_never_basic/src/main.nr +++ /dev/null @@ -1,8 +0,0 @@ -fn main(x: Field, y: pub Field) { - basic_check(x, y); -} - -#[inline(never)] -fn basic_check(x: Field, y: Field) { - assert(x != y); -} diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index b71ea801752..f8432ab94c6 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -6,8 +6,9 @@ use crate::{ }, visitor::expr::{format_seq, NewlineMode}, }; -use noirc_frontend::ast::{ - ItemVisibility, NoirFunction, TraitImplItemKind, UnresolvedTypeData, Visibility, +use noirc_frontend::{ + ast::{ItemVisibility, NoirFunction, TraitImplItemKind, UnresolvedTypeData, Visibility}, + token::SecondaryAttribute, }; use noirc_frontend::{ hir::resolution::errors::Span, @@ -170,7 +171,9 @@ impl super::FmtVisitor<'_> { } for attribute in module.outer_attributes { - self.push_str(&format!("#[{}]\n", attribute.as_ref())); + let is_tag = matches!(attribute, SecondaryAttribute::Tag(_)); + let tag = if is_tag { "'" } else { "" }; + self.push_str(&format!("#[{tag}{}]\n", attribute.as_ref())); self.push_str(&self.indent.to_string()); }