From 569d9231c8c5f834a166027d5f3a70c48a6c2468 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Mon, 7 Apr 2025 16:18:53 -0300 Subject: [PATCH 1/4] feat: allow splicing a resolved function into an attribute name --- compiler/noirc_frontend/src/ast/visitor.rs | 6 +++-- .../noirc_frontend/src/elaborator/comptime.rs | 10 ++++--- compiler/noirc_frontend/src/lexer/token.rs | 26 +++++++++++++++++-- compiler/noirc_frontend/src/parser/parser.rs | 12 +++++++++ .../src/parser/parser/attributes.rs | 22 ++++++++++++---- .../src/parser/parser/expression.rs | 9 +------ .../comptime_attribute/Nargo.toml | 7 +++++ .../comptime_attribute/src/main.nr | 21 +++++++++++++++ tooling/lsp/src/attribute_reference_finder.rs | 7 +++-- tooling/lsp/src/requests/completion.rs | 12 ++++++--- tooling/lsp/src/with_file.rs | 9 +++++-- tooling/nargo_fmt/src/formatter/attribute.rs | 11 +++++--- 12 files changed, 121 insertions(+), 31 deletions(-) create mode 100644 test_programs/compile_success_empty/comptime_attribute/Nargo.toml create mode 100644 test_programs/compile_success_empty/comptime_attribute/src/main.nr diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index 9f9aa13e966..38128b192aa 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -18,7 +18,7 @@ use crate::{ }, parser::{Item, ItemKind, ParsedSubModule}, signed_field::SignedField, - token::{FmtStrFragment, MetaAttribute, SecondaryAttribute, Tokens}, + token::{FmtStrFragment, MetaAttribute, MetaAttributeName, SecondaryAttribute, Tokens}, }; use super::{ @@ -1658,7 +1658,9 @@ impl MetaAttribute { } pub fn accept_children(&self, visitor: &mut impl Visitor) { - self.name.accept(visitor); + if let MetaAttributeName::Path(path) = &self.name { + path.accept(visitor); + } visit_expressions(&self.arguments, visitor); } } diff --git a/compiler/noirc_frontend/src/elaborator/comptime.rs b/compiler/noirc_frontend/src/elaborator/comptime.rs index 7acedfcb933..9d8f5dc1250 100644 --- a/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -21,7 +21,7 @@ use crate::{ hir_def::expr::{HirExpression, HirIdent}, node_interner::{DefinitionKind, DependencyId, FuncId, NodeInterner, TraitId, TypeId}, parser::{Item, ItemKind}, - token::{MetaAttribute, SecondaryAttribute}, + token::{MetaAttribute, MetaAttributeName, SecondaryAttribute}, }; use super::{ElaborateReason, Elaborator, FunctionContext, ResolverMeta}; @@ -185,8 +185,12 @@ impl<'context> Elaborator<'context> { self.local_module = attribute_context.attribute_module; let location = attribute.location; - let function = - Expression { kind: ExpressionKind::Variable(attribute.name.clone()), location }; + let kind = match &attribute.name { + MetaAttributeName::Path(path) => ExpressionKind::Variable(path.clone()), + MetaAttributeName::Resolved(expr_id) => ExpressionKind::Resolved(*expr_id), + }; + + let function = Expression { kind, location }; let arguments = attribute.arguments.clone(); // Elaborate the function, rolling back any errors generated in case it is unknown diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 582beda4aee..2165b91b354 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -1020,7 +1020,13 @@ impl SecondaryAttribute { SecondaryAttribute::Export => Some("export".to_string()), SecondaryAttribute::Field(_) => Some("field".to_string()), SecondaryAttribute::Tag(custom) => custom.name(), - SecondaryAttribute::Meta(meta) => Some(meta.name.last_name().to_string()), + SecondaryAttribute::Meta(meta) => match &meta.name { + MetaAttributeName::Path(path) => Some(path.last_name().to_string()), + MetaAttributeName::Resolved(_) => { + // TODO: Resolve the expression to get the name + None + } + }, SecondaryAttribute::Abi(_) => Some("abi".to_string()), SecondaryAttribute::Varargs => Some("varargs".to_string()), SecondaryAttribute::UseCallersScope => Some("use_callers_scope".to_string()), @@ -1066,7 +1072,7 @@ impl fmt::Display for SecondaryAttribute { #[derive(PartialEq, Eq, Debug, Clone)] pub struct MetaAttribute { - pub name: Path, + pub name: MetaAttributeName, pub arguments: Vec, pub location: Location, } @@ -1083,6 +1089,22 @@ impl Display for MetaAttribute { } } +#[derive(PartialEq, Eq, Debug, Clone)] +pub enum MetaAttributeName { + /// For example `foo::bar` in `#[foo::bar(...)]` + Path(Path), + /// For example `$expr` in `#[$expr(...)]` inside a `quote { ... }` expression. + Resolved(ExprId), +} + +impl Display for MetaAttributeName { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MetaAttributeName::Path(path) => path.fmt(f), + MetaAttributeName::Resolved(_) => write!(f, "(quoted)"), + } + } +} #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] pub struct CustomAttribute { pub contents: String, diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index b797a15f0c1..4f3d91f8cf9 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -6,6 +6,7 @@ use noirc_errors::{Location, Span}; use crate::{ ast::{Ident, ItemVisibility}, lexer::{Lexer, lexer::LocatedTokenResult}, + node_interner::ExprId, token::{FmtStrFragment, IntType, Keyword, LocatedToken, Token, TokenKind, Tokens}, }; @@ -348,6 +349,17 @@ impl<'a> Parser<'a> { } } + fn eat_unquote_marker(&mut self) -> Option { + if let Some(token) = self.eat_kind(TokenKind::UnquoteMarker) { + match token.into_token() { + Token::UnquoteMarker(expr_id) => return Some(expr_id), + _ => unreachable!(""), + } + } + + None + } + fn eat_attribute_start(&mut self) -> Option { if matches!(self.token.token(), Token::AttributeStart { is_inner: false, .. }) { let token = self.bump(); diff --git a/compiler/noirc_frontend/src/parser/parser/attributes.rs b/compiler/noirc_frontend/src/parser/parser/attributes.rs index 5fe4497b33b..34c069c50bf 100644 --- a/compiler/noirc_frontend/src/parser/parser/attributes.rs +++ b/compiler/noirc_frontend/src/parser/parser/attributes.rs @@ -4,7 +4,9 @@ use crate::ast::{Expression, ExpressionKind, Ident, Literal, Path}; use crate::lexer::errors::LexerErrorKind; use crate::parser::ParserErrorReason; use crate::parser::labels::ParsingRuleLabel; -use crate::token::{Attribute, FunctionAttribute, FuzzingScope, MetaAttribute, TestScope, Token}; +use crate::token::{ + Attribute, FunctionAttribute, FuzzingScope, MetaAttribute, MetaAttributeName, TestScope, Token, +}; use crate::token::{CustomAttribute, SecondaryAttribute}; use super::Parser; @@ -138,8 +140,9 @@ impl Parser<'_> { { // This is a Meta attribute with the syntax `keyword(arg1, arg2, .., argN)` let path = Path::from_single(self.token.to_string(), self.current_token_location); + let name = MetaAttributeName::Path(path); self.bump(); - self.parse_meta_attribute(path, start_location) + self.parse_meta_attribute(name, start_location) } else if let Some(path) = self.parse_path_no_turbofish() { if let Some(ident) = path.as_ident() { if ident.as_str() == "test" { @@ -156,15 +159,24 @@ impl Parser<'_> { } } else { // This is a Meta attribute with the syntax `path(arg1, arg2, .., argN)` - self.parse_meta_attribute(path, start_location) + let name = MetaAttributeName::Path(path); + self.parse_meta_attribute(name, start_location) } + } else if let Some(expr_id) = self.eat_unquote_marker() { + // This is a Meta attribute with the syntax `$expr(arg1, arg2, .., argN)` + let name = MetaAttributeName::Resolved(expr_id); + self.parse_meta_attribute(name, start_location) } else { self.expected_label(ParsingRuleLabel::Path); self.parse_tag_attribute(start_location) } } - fn parse_meta_attribute(&mut self, name: Path, start_location: Location) -> Attribute { + fn parse_meta_attribute( + &mut self, + name: MetaAttributeName, + start_location: Location, + ) -> Attribute { let arguments = self.parse_arguments().unwrap_or_default(); self.skip_until_right_bracket(); Attribute::Secondary(SecondaryAttribute::Meta(MetaAttribute { @@ -236,7 +248,7 @@ impl Parser<'_> { self.parse_no_args_attribute(ident, arguments, attr) } _ => Attribute::Secondary(SecondaryAttribute::Meta(MetaAttribute { - name: Path::from_ident(ident.clone()), + name: MetaAttributeName::Path(Path::from_ident(ident.clone())), arguments, location: self.location_since(start_location), })), diff --git a/compiler/noirc_frontend/src/parser/parser/expression.rs b/compiler/noirc_frontend/src/parser/parser/expression.rs index 4d593f93b8b..dbf77358b6b 100644 --- a/compiler/noirc_frontend/src/parser/parser/expression.rs +++ b/compiler/noirc_frontend/src/parser/parser/expression.rs @@ -403,14 +403,7 @@ impl Parser<'_> { /// ResolvedExpression = unquote_marker fn parse_resolved_expr(&mut self) -> Option { - if let Some(token) = self.eat_kind(TokenKind::UnquoteMarker) { - match token.into_token() { - Token::UnquoteMarker(expr_id) => return Some(ExpressionKind::Resolved(expr_id)), - _ => unreachable!(""), - } - } - - None + Some(ExpressionKind::Resolved(self.eat_unquote_marker()?)) } /// InternedExpression = interned_expr diff --git a/test_programs/compile_success_empty/comptime_attribute/Nargo.toml b/test_programs/compile_success_empty/comptime_attribute/Nargo.toml new file mode 100644 index 00000000000..c5b9ca89240 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_attribute/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_type" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_attribute/src/main.nr b/test_programs/compile_success_empty/comptime_attribute/src/main.nr new file mode 100644 index 00000000000..d83534091f8 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_attribute/src/main.nr @@ -0,0 +1,21 @@ +#[add_foo] +mod moo { + pub comptime fn add_fn(_: FunctionDefinition, name: Quoted) -> Quoted { + quote { + pub fn $name() {} + } + } +} + +comptime fn add_foo(_: Module) -> Quoted { + let add_fn = moo::add_fn; + quote { + #[$add_fn(quote { bar })] + pub fn foo() {} + } +} + +fn main() { + moo::foo(); + moo::bar(); +} diff --git a/tooling/lsp/src/attribute_reference_finder.rs b/tooling/lsp/src/attribute_reference_finder.rs index d71a565b2f8..377734f5639 100644 --- a/tooling/lsp/src/attribute_reference_finder.rs +++ b/tooling/lsp/src/attribute_reference_finder.rs @@ -18,7 +18,7 @@ use noirc_frontend::{ }, node_interner::ReferenceId, parser::ParsedSubModule, - token::MetaAttribute, + token::{MetaAttribute, MetaAttributeName}, usage_tracker::UsageTracker, }; @@ -94,7 +94,10 @@ impl Visitor for AttributeReferenceFinder<'_> { return false; } - let path = attribute.name.clone(); + let MetaAttributeName::Path(path) = attribute.name.clone() else { + return false; + }; + // The path here must resolve to a function and it's a simple path (can't have turbofish) // so it can (and must) be solved as an import. let Ok(Some((module_def_id, _, _))) = resolve_import( diff --git a/tooling/lsp/src/requests/completion.rs b/tooling/lsp/src/requests/completion.rs index 5eb66e8aca6..6d7cbc47237 100644 --- a/tooling/lsp/src/requests/completion.rs +++ b/tooling/lsp/src/requests/completion.rs @@ -34,7 +34,7 @@ use noirc_frontend::{ hir_def::traits::Trait, node_interner::{FuncId, NodeInterner, ReferenceId, TypeId}, parser::{Item, ItemKind, ParsedSubModule}, - token::{MetaAttribute, Token, Tokens}, + token::{MetaAttribute, MetaAttributeName, Token, Tokens}, }; use sort_text::underscore_sort_text; @@ -1830,11 +1830,15 @@ impl Visitor for NodeFinder<'_> { } fn visit_meta_attribute(&mut self, attribute: &MetaAttribute, target: AttributeTarget) -> bool { - if self.byte_index == attribute.name.location.span.end() as usize { - self.suggest_builtin_attributes(&attribute.name.to_string(), target); + let MetaAttributeName::Path(path) = &attribute.name else { + return true; + }; + + if self.byte_index == path.location.span.end() as usize { + self.suggest_builtin_attributes(&path.to_string(), target); } - self.find_in_path(&attribute.name, RequestedItems::OnlyAttributeFunctions(target)); + self.find_in_path(path, RequestedItems::OnlyAttributeFunctions(target)); true } diff --git a/tooling/lsp/src/with_file.rs b/tooling/lsp/src/with_file.rs index ccd4d70c88d..3625de465c1 100644 --- a/tooling/lsp/src/with_file.rs +++ b/tooling/lsp/src/with_file.rs @@ -18,7 +18,8 @@ use noirc_frontend::{ }, parser::{Item, ItemKind, ParsedSubModule}, token::{ - Attributes, FmtStrFragment, LocatedToken, MetaAttribute, SecondaryAttribute, Token, Tokens, + Attributes, FmtStrFragment, LocatedToken, MetaAttribute, MetaAttributeName, + SecondaryAttribute, Token, Tokens, }, }; @@ -594,8 +595,12 @@ fn secondary_attribute_with_file( } fn meta_attribute_with_file(meta_attribute: MetaAttribute, file: FileId) -> MetaAttribute { + let name = match meta_attribute.name { + MetaAttributeName::Path(path) => MetaAttributeName::Path(path_with_file(path, file)), + MetaAttributeName::Resolved(expr_id) => MetaAttributeName::Resolved(expr_id), + }; MetaAttribute { - name: path_with_file(meta_attribute.name, file), + name, arguments: expressions_with_file(meta_attribute.arguments, file), location: location_with_file(meta_attribute.location, file), } diff --git a/tooling/nargo_fmt/src/formatter/attribute.rs b/tooling/nargo_fmt/src/formatter/attribute.rs index 66672d6eef0..08990f32988 100644 --- a/tooling/nargo_fmt/src/formatter/attribute.rs +++ b/tooling/nargo_fmt/src/formatter/attribute.rs @@ -1,6 +1,6 @@ use noirc_frontend::token::{ - Attribute, Attributes, FunctionAttribute, FuzzingScope, MetaAttribute, SecondaryAttribute, - TestScope, Token, + Attribute, Attributes, FunctionAttribute, FuzzingScope, MetaAttribute, MetaAttributeName, + SecondaryAttribute, TestScope, Token, }; use crate::chunks::ChunkGroup; @@ -171,7 +171,12 @@ impl Formatter<'_> { fn format_meta_attribute(&mut self, meta_attribute: MetaAttribute) { self.write_current_token_and_bump(); // #[ self.skip_comments_and_whitespace(); - self.format_path(meta_attribute.name); + match meta_attribute.name { + MetaAttributeName::Path(path) => self.format_path(path), + MetaAttributeName::Resolved(_) => { + unreachable!("Resolved MetaAttributeName should not happen when formatting a file") + } + } self.skip_comments_and_whitespace(); if self.is_at(Token::LeftParen) { let comments_count_before_arguments = self.written_comments_count; From a9436cecee0bebf11d3cbdcf2b666ac9fcfdada2 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Wed, 9 Apr 2025 16:28:52 -0300 Subject: [PATCH 2/4] Update compiler/noirc_frontend/src/parser/parser.rs Co-authored-by: Michael J Klein --- compiler/noirc_frontend/src/parser/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 4f3d91f8cf9..aeea6cfaa72 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -353,7 +353,7 @@ impl<'a> Parser<'a> { if let Some(token) = self.eat_kind(TokenKind::UnquoteMarker) { match token.into_token() { Token::UnquoteMarker(expr_id) => return Some(expr_id), - _ => unreachable!(""), + _ => unreachable!("Expected only `UnquoteMarker` to have `TokenKind::UnquoteMarker`"), } } From 1c2c9ec0da6de6cf60e01afae9dc14094a42ba22 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Wed, 9 Apr 2025 16:37:11 -0300 Subject: [PATCH 3/4] Name for MetaAttributeName::Resolved --- .../src/hir/comptime/interpreter/builtin.rs | 10 +++-- .../interpreter/builtin/builtin_helpers.rs | 37 +++++++++++++++++-- compiler/noirc_frontend/src/lexer/token.rs | 25 +------------ .../comptime_attribute/src/main.nr | 7 ++-- 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index b1fddd6ede1..eefa8995b49 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -537,7 +537,7 @@ fn type_def_has_named_attribute( let name = get_str(interner, name)?; - Ok(Value::Bool(has_named_attribute(&name, interner.type_attributes(&type_id)))) + Ok(Value::Bool(has_named_attribute(&name, interner.type_attributes(&type_id), interner))) } /// fn fields(self, generic_args: [Type]) -> [(Quoted, Type)] @@ -2505,7 +2505,7 @@ fn function_def_has_named_attribute( } } - Ok(Value::Bool(has_named_attribute(name, &modifiers.attributes.secondary))) + Ok(Value::Bool(has_named_attribute(name, &modifiers.attributes.secondary, interner))) } fn function_def_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult { @@ -2878,7 +2878,11 @@ fn module_has_named_attribute( let name = get_str(interpreter.elaborator.interner, name)?; - Ok(Value::Bool(has_named_attribute(&name, &module_data.attributes))) + Ok(Value::Bool(has_named_attribute( + &name, + &module_data.attributes, + interpreter.elaborator.interner, + ))) } // fn is_contract(self) -> bool diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs index 4eaba7c3868..4da6be3d818 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs @@ -9,9 +9,10 @@ use crate::elaborator::Elaborator; use crate::hir::comptime::display::tokens_to_string; use crate::hir::comptime::value::unwrap_rc; use crate::hir::def_collector::dc_crate::CompilationError; +use crate::hir_def::expr::HirExpression; use crate::lexer::Lexer; use crate::parser::{Parser, ParserError}; -use crate::token::LocatedToken; +use crate::token::{LocatedToken, MetaAttributeName}; use crate::{DataType, Kind, Shared}; use crate::{ QuotedType, Type, @@ -575,9 +576,13 @@ pub(super) fn block_expression_to_value(block_expr: BlockExpression) -> Value { Value::Slice(statements, typ) } -pub(super) fn has_named_attribute(name: &str, attributes: &[SecondaryAttribute]) -> bool { +pub(super) fn has_named_attribute( + name: &str, + attributes: &[SecondaryAttribute], + interner: &NodeInterner, +) -> bool { for attribute in attributes { - if let Some(attribute_name) = attribute.name() { + if let Some(attribute_name) = secondary_attribute_name(attribute, interner) { if name == attribute_name { return true; } @@ -587,6 +592,32 @@ pub(super) fn has_named_attribute(name: &str, attributes: &[SecondaryAttribute]) false } +fn secondary_attribute_name( + attribute: &SecondaryAttribute, + interner: &NodeInterner, +) -> Option { + match attribute { + SecondaryAttribute::Deprecated(_) => Some("deprecated".to_string()), + SecondaryAttribute::ContractLibraryMethod => Some("contract_library_method".to_string()), + SecondaryAttribute::Export => Some("export".to_string()), + SecondaryAttribute::Field(_) => Some("field".to_string()), + SecondaryAttribute::Tag(custom) => custom.name(), + SecondaryAttribute::Meta(meta) => match &meta.name { + MetaAttributeName::Path(path) => Some(path.last_name().to_string()), + MetaAttributeName::Resolved(expr_id) => { + let HirExpression::Ident(ident, _) = interner.expression(expr_id) else { + return None; + }; + interner.try_definition(ident.id).map(|def| def.name.clone()) + } + }, + SecondaryAttribute::Abi(_) => Some("abi".to_string()), + SecondaryAttribute::Varargs => Some("varargs".to_string()), + SecondaryAttribute::UseCallersScope => Some("use_callers_scope".to_string()), + SecondaryAttribute::Allow(_) => Some("allow".to_string()), + } +} + pub(super) fn quote_ident(ident: &Ident, location: Location) -> Value { Value::Quoted(ident_to_tokens(ident, location)) } diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 2165b91b354..c24c2268f0b 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -1011,29 +1011,6 @@ pub enum SecondaryAttribute { } impl SecondaryAttribute { - pub(crate) fn name(&self) -> Option { - match self { - SecondaryAttribute::Deprecated(_) => Some("deprecated".to_string()), - SecondaryAttribute::ContractLibraryMethod => { - Some("contract_library_method".to_string()) - } - SecondaryAttribute::Export => Some("export".to_string()), - SecondaryAttribute::Field(_) => Some("field".to_string()), - SecondaryAttribute::Tag(custom) => custom.name(), - SecondaryAttribute::Meta(meta) => match &meta.name { - MetaAttributeName::Path(path) => Some(path.last_name().to_string()), - MetaAttributeName::Resolved(_) => { - // TODO: Resolve the expression to get the name - None - } - }, - SecondaryAttribute::Abi(_) => Some("abi".to_string()), - SecondaryAttribute::Varargs => Some("varargs".to_string()), - SecondaryAttribute::UseCallersScope => Some("use_callers_scope".to_string()), - SecondaryAttribute::Allow(_) => Some("allow".to_string()), - } - } - pub(crate) fn is_allow_unused_variables(&self) -> bool { match self { SecondaryAttribute::Allow(string) => string == "unused_variables", @@ -1115,7 +1092,7 @@ pub struct CustomAttribute { } impl CustomAttribute { - fn name(&self) -> Option { + pub(crate) fn name(&self) -> Option { let mut lexer = Lexer::new_with_dummy_file(&self.contents); let token = lexer.next()?.ok()?; if let Token::Ident(ident) = token.into_token() { Some(ident) } else { None } diff --git a/test_programs/compile_success_empty/comptime_attribute/src/main.nr b/test_programs/compile_success_empty/comptime_attribute/src/main.nr index d83534091f8..70f0a86153d 100644 --- a/test_programs/compile_success_empty/comptime_attribute/src/main.nr +++ b/test_programs/compile_success_empty/comptime_attribute/src/main.nr @@ -1,6 +1,7 @@ #[add_foo] mod moo { - pub comptime fn add_fn(_: FunctionDefinition, name: Quoted) -> Quoted { + pub comptime fn add_fn(f: FunctionDefinition, name: Quoted) -> Quoted { + assert(f.has_named_attribute("add_fn")); quote { pub fn $name() {} } @@ -8,9 +9,9 @@ mod moo { } comptime fn add_foo(_: Module) -> Quoted { - let add_fn = moo::add_fn; + let func = moo::add_fn; quote { - #[$add_fn(quote { bar })] + #[$func(quote { bar })] pub fn foo() {} } } From 1406f6e64009000e0b3402c17f3f5f98f5967f91 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Wed, 9 Apr 2025 16:42:45 -0300 Subject: [PATCH 4/4] cargo fmt --- compiler/noirc_frontend/src/parser/parser.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index aeea6cfaa72..c39353cb233 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -353,7 +353,9 @@ impl<'a> Parser<'a> { if let Some(token) = self.eat_kind(TokenKind::UnquoteMarker) { match token.into_token() { Token::UnquoteMarker(expr_id) => return Some(expr_id), - _ => unreachable!("Expected only `UnquoteMarker` to have `TokenKind::UnquoteMarker`"), + _ => { + unreachable!("Expected only `UnquoteMarker` to have `TokenKind::UnquoteMarker`") + } } }