Skip to content

Functions in libraries#29234

Merged
mohammadfawaz merged 1 commit intomasterfrom
mohammadfawaz/functions_in_libs
Mar 26, 2026
Merged

Functions in libraries#29234
mohammadfawaz merged 1 commit intomasterfrom
mohammadfawaz/functions_in_libs

Conversation

@mohammadfawaz
Copy link
Copy Markdown
Collaborator

@mohammadfawaz mohammadfawaz commented Mar 24, 2026

Summary

This PR extends Leo library support (started in #29196 and #29217) to allow fn function definitions inside library files. Library functions are inlined at their call sites by the function-inlining pass, exactly like module helper functions — they have no on-chain footprint and never appear as standalone Aleo functions in the compiled bytecode.

What changed

AST (crates/ast)

  • Library gains a functions: Vec<(Symbol, Function)> field alongside the existing consts and structs.
  • The default visit_library in ProgramVisitor now visits function bodies, so passes that rely on the default (e.g. NameValidationVisitor, StaticAnalyzingVisitor) automatically cover library functions.

Parser (crates/parser)

  • FUNCTION_DEF nodes are now recognized as valid library items in is_library_item.
  • collect_library_item parses them via the existing to_function path with is_in_program_block = false (so all functions get variant Fn; entry-point variants are illegal in libraries).
  • The "not allowed in a library" error message is updated to include fn in the list of allowed items.

Passes (crates/passes)

Pass Change
SSA Forming New LibraryConsumer impl runs SSA on every library function body. consume_stub dispatches FromLibrary through this impl.
Flattening Overrides reconstruct_library to run flattening on library function bodies (requires SSA to have run first).
PathResolution reconstruct_library reconstructs library function bodies.
OptionLowering / StorageLowering Override reconstruct_library to reconstruct consts, structs, and function bodies, setting/restoring self.program around the library scope.
ConstPropagation Skips generic library functions (those with const_parameters) — they cannot be fully evaluated until monomorphized.
GlobalItemsCollection / TypeChecking visit_library now visits function bodies so signatures are registered in the symbol table and type-checked.
Monomorphization Generic library functions reachable from the consuming program are included in the post-order call-graph traversal and monomorphized. reconstruct_library collects monomorphized variants back into the library stub, filtering out the generic originals to prevent "defined multiple times" errors on subsequent TypeChecking iterations. function_map is seeded with library functions before reconstruct_program_scope runs, and library entries are retained across nested FromLeo stub recursions.
FunctionInlining function_map is seeded with all library functions from FromLibrary stubs. The post-order inliner treats library functions identically to module functions: looked up in reconstructed_functions and inlined at every call site. Dead library functions (never called) are dropped before the sanity assert.
CSE / SsaConstPropagation Override reconstruct_library to pass library stubs through unchanged — library functions are already inlined by this stage.

Tests

  • Parser: functions.leo (basic, generic, multi-generic, intra-library call declarations); fn_bad_items_fail.leo (entry-point variants rejected). Existing bad_items_fail.leo and struct_bad_items_fail.leo updated to remove items that are now valid.
  • Passes: new lib_fn_*.leo tests under function_inlining/, flattening/, and ssa_forming/ exercising library functions through individual passes. Pass test infrastructure (test_passes.rs) extended to support the // --- library: NAME --- // / // --- Next Program --- // multi-section format. The flattening_runner now includes SSA forming, matching the real compiler pipeline.
  • Compiler (19 new tests): basic call, intra-library call chain, call chain with struct (pipeline calling translate and distance_sq from the same library), generic function, multi-param generic, generic calling concrete helper, cross-library call, cross-library call with struct (lib B calls lib A functions passing lib A struct types), function using library const, function using library struct locally, tuple return, conditional, called multiple times, dead code, call inside final {} block; plus three fail tests (wrong arg count, wrong arg type, non-const generic arg).
  • Execution (10 new tests): all key passing scenarios exercised end-to-end with concrete input/output verification, including cross-library struct passing and intra-library call chains.

Design notes

No import required. Library items are referenced via lib_name::item path syntax. The dependency entry in program.json is sufficient, matching existing struct/const behavior.

Always inlined. Library functions are unconditionally inlined. The is_library predicate on the symbol table drives this decision throughout the inliner and monomorphizer.

Ordering invariant. SSA forming runs before flattening on library function bodies (via the LibraryConsumer impl and the reconstruct_library override). This matches the program-function pipeline and is required because the flattening pass asserts SSA form on every function body it processes.

Monomorphization + ConstPropUnrollAndMorphing loop. Generic library functions are monomorphized inside the consuming program's reconstruct_program_scope. The resulting instances are collected back into the library stub by reconstruct_library, replacing the generic originals, so the next TypeChecking iteration sees a consistent library with only concrete functions.

@mohammadfawaz mohammadfawaz self-assigned this Mar 24, 2026
@mohammadfawaz mohammadfawaz marked this pull request as ready for review March 24, 2026 16:25
@mohammadfawaz mohammadfawaz requested a review from a team March 24, 2026 16:26
@mohammadfawaz mohammadfawaz added the 🧱 Core Compiler Anything related to the core compiler including parsing, analysis, transforms, codegen, etc. label Mar 24, 2026
@mohammadfawaz mohammadfawaz force-pushed the mohammadfawaz/functions_in_libs branch 2 times, most recently from 8c8e59b to 566bfe2 Compare March 25, 2026 16:27
@mohammadfawaz mohammadfawaz force-pushed the mohammadfawaz/functions_in_libs branch from 566bfe2 to 8e74331 Compare March 26, 2026 02:32
Copy link
Copy Markdown
Collaborator

@mitchmindtree mitchmindtree left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, seems pretty straightforward!

@mohammadfawaz mohammadfawaz merged commit ee07305 into master Mar 26, 2026
7 checks passed
@mohammadfawaz mohammadfawaz deleted the mohammadfawaz/functions_in_libs branch March 26, 2026 02:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🧱 Core Compiler Anything related to the core compiler including parsing, analysis, transforms, codegen, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants