Merged
Conversation
8c8e59b to
566bfe2
Compare
566bfe2 to
8e74331
Compare
mitchmindtree
approved these changes
Mar 26, 2026
Collaborator
mitchmindtree
left a comment
There was a problem hiding this comment.
Nice work, seems pretty straightforward!
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.
Summary
This PR extends Leo library support (started in #29196 and #29217) to allow
fnfunction 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)Librarygains afunctions: Vec<(Symbol, Function)>field alongside the existingconstsandstructs.visit_libraryinProgramVisitornow visits function bodies, so passes that rely on the default (e.g.NameValidationVisitor,StaticAnalyzingVisitor) automatically cover library functions.Parser (
crates/parser)FUNCTION_DEFnodes are now recognized as valid library items inis_library_item.collect_library_itemparses them via the existingto_functionpath withis_in_program_block = false(so all functions get variantFn; entry-point variants are illegal in libraries).fnin the list of allowed items.Passes (
crates/passes)LibraryConsumerimpl runs SSA on every library function body.consume_stubdispatchesFromLibrarythrough this impl.reconstruct_libraryto run flattening on library function bodies (requires SSA to have run first).reconstruct_libraryreconstructs library function bodies.reconstruct_libraryto reconstruct consts, structs, and function bodies, setting/restoringself.programaround the library scope.const_parameters) — they cannot be fully evaluated until monomorphized.visit_librarynow visits function bodies so signatures are registered in the symbol table and type-checked.reconstruct_librarycollects monomorphized variants back into the library stub, filtering out the generic originals to prevent "defined multiple times" errors on subsequent TypeChecking iterations.function_mapis seeded with library functions beforereconstruct_program_scoperuns, and library entries are retained across nestedFromLeostub recursions.function_mapis seeded with all library functions fromFromLibrarystubs. The post-order inliner treats library functions identically to module functions: looked up inreconstructed_functionsand inlined at every call site. Dead library functions (never called) are dropped before the sanity assert.reconstruct_libraryto pass library stubs through unchanged — library functions are already inlined by this stage.Tests
functions.leo(basic, generic, multi-generic, intra-library call declarations);fn_bad_items_fail.leo(entry-point variants rejected). Existingbad_items_fail.leoandstruct_bad_items_fail.leoupdated to remove items that are now valid.lib_fn_*.leotests underfunction_inlining/,flattening/, andssa_forming/exercising library functions through individual passes. Pass test infrastructure (test_passes.rs) extended to support the// --- library: NAME --- ///// --- Next Program --- //multi-section format. Theflattening_runnernow includes SSA forming, matching the real compiler pipeline.pipelinecallingtranslateanddistance_sqfrom 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 insidefinal {}block; plus three fail tests (wrong arg count, wrong arg type, non-const generic arg).Design notes
No
importrequired. Library items are referenced vialib_name::itempath syntax. The dependency entry inprogram.jsonis sufficient, matching existing struct/const behavior.Always inlined. Library functions are unconditionally inlined. The
is_librarypredicate 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
LibraryConsumerimpl and thereconstruct_libraryoverride). 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 byreconstruct_library, replacing the generic originals, so the next TypeChecking iteration sees a consistent library with only concrete functions.