chore: resolve builtin/foreign attribute names to a shared enum - #13521
Open
asterite wants to merge 1 commit into
Open
chore: resolve builtin/foreign attribute names to a shared enum#13521asterite wants to merge 1 commit into
asterite wants to merge 1 commit into
Conversation
The name in a #[builtin]/#[foreign] attribute was carried as a String all the way through the pipeline and re-matched textually at every consumer: the comptime interpreter's dispatch, the monomorphizer's HandledOpcode, Definition::Builtin/LowLevel, Intrinsic::lookup in SSA generation, and the ownership pass's clone-elision list. The names now resolve once to noirc_frontend::shared::Builtin, a single flat enum covering all 148 stdlib builtins, the 12 foreign functions, and the compiler-emitted black box names. Attribute tokens still hold free-form strings (so malformed or unknown names parse and error with a diagnostic); resolution happens at the semantic boundaries: the comptime interpreter, and the monomorphizer when constructing Definition::Builtin/LowLevel. Every downstream consumer now matches on enum variants. Behavior changes: - Calling a builtin with an unknown name is now a proper MonomorphizationError::UnknownBuiltin diagnostic; previously it survived to SSA generation and panicked there. - The five unresolved_type_* comptime dispatch arms (and their helper functions) are deleted: stdlib no longer declares those builtins and only stdlib may declare builtins, so they were unreachable. The clone-elision sync test now iterates Builtin::iter() exhaustively instead of a hand-maintained name list. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
asterite
force-pushed
the
ab/builtin-enum
branch
from
August 13, 2026 16:17
061bdb6 to
db8f2f0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #13520 — the first three commits are that PR; review only the last commit here.
Problem
The name in a
#[builtin(name)]/#[foreign(name)]attribute was carried as aStringthrough the whole pipeline and re-matched textually at every consumer: the comptime interpreter's ~150-arm dispatch, the monomorphizer'sHandledOpcode,Definition::Builtin/LowLevel,Intrinsic::lookupin SSA generation, and the ownership pass's clone-elision list (added in #13520). Nothing tied these tables together except one test, and an unknown name silently survived to SSA generation where it panicked.Change
Builtin/foreign names now resolve once to
noirc_frontend::shared::Builtin— a single enum (the two attribute kinds share one namespace at consumption) covering all 148 stdlib#[builtin]names and the 12#[foreign]names, grouped by consumer: SSA intrinsics, monomorphizer-evaluated, comptime-only. The ACIR black box functions are not repeated as variants: they nest asBuiltin::BlackBox(BlackBoxFunc), so acvm's enum stays the single source of those names and a new black box function is aBuiltinby construction.strumderives providelookup/name/iterfor the unit variants (the payload variant is#[strum(disabled)]and handled explicitly), with a round-trip test.Attribute tokens still hold free-form strings, so malformed or unknown names parse normally; resolution happens at the semantic boundaries:
call_special(thencall_builtin/call_foreignmatch enum variants),Definition::Builtin(Builtin)/LowLevel(Builtin),Builtin→Intrinsicvia the newIntrinsic::from_builtin(Intrinsic::lookup(&str)remains only for the SSA text parser).Oracle (
#[oracle]) names stay strings deliberately: they are an open, user-extensible namespace.Behavior changes
MonomorphizationError::UnknownBuiltindiagnostic (with test); previously it was an SSA-genpanic!.unresolved_type_*comptime dispatch arms and their helpers are deleted: stdlib no longer declares those builtins, and only stdlib may declare builtins, so they were unreachable.BlackBoxFunc::AND/XOR/RANGEare filtered out ofBuiltin::lookup: they are not callable functions (the compiler emits their opcodes from binary ops, casts and range checks), so names like#[foreign(and)]— never declared anywhere — now error like any unknown name.Follow-on wins
Builtin::iter()exhaustively instead of a hand-maintained name list, andbuiltin_supports_clone_elisionmatches variants.#[builtin(foo)], which the new diagnostic rightly rejects; it now uses the real generic builtinblack_boxand tests the same instantiation behavior.Validation
noirc_frontend+noirc_evaluator(4192 tests), the fullnargo_cli --test executesuite (9350 tests), stdlib tests (431 × 9 configs), AST fuzzer smoke, clippy, and the enum round-trip/black-box coverage tests all pass.🤖 Generated with Claude Code