BEP-062 AnyFunction slice: baml.AnyFunction + reflect.signature/call_any - #4099
Conversation
…t.signature/call_any
- baml.AnyFunction builtin interface (Returns/Throws pins, both default
unknown): conformance derived in the subtype engine for every function
type, pins covariant; implements blocks rejected (E0153), generic bounds
rejected (E0154)
- reflect.signature(f) -> Signature { args: Arg[], kwargs: map<string, Arg>,
returns, throws }; Arg { name, docstring, type } (docstring null until
parameter docstrings exist)
- reflect.call_any<R, E>(f, args, kwargs = {}) -> R throws E |
InvalidArgumentError: runtime-checked dynamic call; absent kwargs fire the
callee's own defaults; R/E infer from the argument's pins
- function values unified on the heap: a plain reference emits a pooled,
interned empty-type-args GenericFunction wrapper (identity preserved), so
a raw Function object is never a data value; non-function global item
reads split off as Constant::GlobalItem
- lambda signatures recorded at MIR lowering (mir::RuntimeSignature) and
stamped by the same emit path as top-level declarations
- throws usable as a field/member name (Signature.throws)
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds BEP-062 ChangesAnyFunction contracts and typing
Builtin-interface restrictions and diagnostics
Compiler function values and signatures
Runtime reflection and dynamic calls
Reflective invocation and typing coverage
Estimated code review effort: 5 (Critical) | ~90 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant ReflectNative
participant BexVm
participant Callee
Caller->>ReflectNative: pass AnyFunction and argument map
ReflectNative->>BexVm: reconstruct callable signature
BexVm-->>ReflectNative: return parameters and metadata
ReflectNative->>ReflectNative: validate arguments and types
ReflectNative->>Callee: dispatch ordered arguments
Callee-->>Caller: return result or typed error
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
baml_language/crates/baml_tests/projects/diagnostic_errors/anyfunction/bans.baml (1)
1-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing "impl generics" case from the stated coverage.
The header comment claims E0154 coverage on "functions, classes, impl generics, or associated types," but the file only exercises function (
pick), class (Holder), and associated-type (Registry.Callee) bounds. There's no case for a generic bound on animplblock itself (e.g.impl<T extends baml.AnyFunction> SomeIface for SomeType<T> {}).If
impl_rules.rsdiagnostics for this specific shape aren't already covered elsewhere, consider adding a case here to match the doc comment's claim.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@baml_language/crates/baml_tests/projects/diagnostic_errors/anyfunction/bans.baml` around lines 1 - 22, The diagnostic fixture lacks coverage for E0154 on impl-block generics. Add a representative impl declaration with a generic parameter bounded by baml.AnyFunction, such as an impl of an existing interface for a generic type, and ensure it exercises the expected diagnostic without changing the existing function, class, or associated-type cases.baml_language/crates/bex_vm/src/package_reflect/mod.rs (1)
1-345: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider colocated unit tests for the new dispatch/validation logic.
The core validation logic (
value_fits,call_shape_ty, arity/optional-argument matching incall_any) is pure enough to unit test directly in this crate, rather than relying solely on the integration-style coverage inbaml_tests. As per path instructions,**/*.rs: "Prefer writing Rust unit tests over integration tests where possible."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@baml_language/crates/bex_vm/src/package_reflect/mod.rs` around lines 1 - 345, Add colocated Rust unit tests in the same module for the new validation helpers and call_any argument matching. Cover value_fits type compatibility, call_shape_ty construction, positional arity mismatches, unknown named arguments, and valid optional-argument handling, using existing crate test utilities and preserving the current dispatch behavior.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@baml_language/crates/baml_compiler_parser/src/parser.rs`:
- Around line 523-528: Extend unquoted key recognition for TokenKind::Throws
throughout object literal parsing: update brace_content_looks_like_fields,
parse_object_literal_body, and parse_object_field to use at_member_name() or
explicitly accept Throws alongside Word and Client. Also update parse_map_entry
and looks_like_map if they independently gate unquoted map keys, preserving
existing behavior for all other keys.
In `@baml_language/crates/bex_vm/src/vm.rs`:
- Around line 1229-1280: Update function_callable_signature to preserve
unresolved TypeVar entries from stored function signatures instead of routing
every parameter, return type, and throws type through realized_arg, which
currently causes generic callables to return None. Use the existing coarse
generic representation expected by the GenericFunction reflection path, without
substituting gf.type_args, while retaining current receiver dropping and
parameter metadata behavior.
---
Nitpick comments:
In
`@baml_language/crates/baml_tests/projects/diagnostic_errors/anyfunction/bans.baml`:
- Around line 1-22: The diagnostic fixture lacks coverage for E0154 on
impl-block generics. Add a representative impl declaration with a generic
parameter bounded by baml.AnyFunction, such as an impl of an existing interface
for a generic type, and ensure it exercises the expected diagnostic without
changing the existing function, class, or associated-type cases.
In `@baml_language/crates/bex_vm/src/package_reflect/mod.rs`:
- Around line 1-345: Add colocated Rust unit tests in the same module for the
new validation helpers and call_any argument matching. Cover value_fits type
compatibility, call_shape_ty construction, positional arity mismatches, unknown
named arguments, and valid optional-argument handling, using existing crate test
utilities and preserving the current dispatch behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 70b07890-1632-4d62-83e6-2de41ad278ff
⛔ Files ignored due to path filters (115)
baml_language/crates/baml_tests/snapshots/baml_src/_root.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/baml_src/closures.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/baml_src/exceptions.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/baml_src/functions.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/baml_src/optional_function_parameters.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/anyfunction_reflect/baml_tests__compiles__anyfunction_reflect__01_lexer__main.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/anyfunction_reflect/baml_tests__compiles__anyfunction_reflect__02_parser__main.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/anyfunction_reflect/baml_tests__compiles__anyfunction_reflect__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/anyfunction_reflect/baml_tests__compiles__anyfunction_reflect__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/anyfunction_reflect/baml_tests__compiles__anyfunction_reflect__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/anyfunction_reflect/baml_tests__compiles__anyfunction_reflect__05_diagnostics.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/anyfunction_reflect/baml_tests__compiles__anyfunction_reflect__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/anyfunction_reflect/baml_tests__compiles__anyfunction_reflect__10_formatter__main.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/backtick_decl_slots/baml_tests__compiles__backtick_decl_slots__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/backtick_decl_slots/baml_tests__compiles__backtick_decl_slots__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/backtick_dedent/baml_tests__compiles__backtick_dedent__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/backtick_strings/baml_tests__compiles__backtick_strings__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_literal/baml_tests__compiles__bigint_literal__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/byte_string_literals/baml_tests__compiles__byte_string_literals__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/catch_all_keyword/baml_tests__compiles__catch_all_keyword__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/catch_all_panics/baml_tests__compiles__catch_all_panics__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/catch_arm_return/baml_tests__compiles__catch_arm_return__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/catch_throw/baml_tests__compiles__catch_throw__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/closure_loop_variable/baml_tests__compiles__closure_loop_variable__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/closures/baml_tests__compiles__closures__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/comment_after_string_in_config/baml_tests__compiles__comment_after_string_in_config__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/comment_in_type/baml_tests__compiles__comment_in_type__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/comment_in_type/baml_tests__compiles__comment_in_type__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/config_dictionary/baml_tests__compiles__config_dictionary__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/config_model_string/baml_tests__compiles__config_model_string__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/deep_method_call/baml_tests__compiles__deep_method_call__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/function_call/baml_tests__compiles__function_call__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/generic_field_chain/baml_tests__compiles__generic_field_chain__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/generic_match_typevar_arm/baml_tests__compiles__generic_match_typevar_arm__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/host_callable_call/baml_tests__compiles__host_callable_call__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/is_operator/baml_tests__compiles__is_operator__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_alias_basic/baml_tests__compiles__json_alias_basic__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_cross_namespace_static_call/baml_tests__compiles__json_cross_namespace_static_call__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_llm_return_type/baml_tests__compiles__json_llm_return_type__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_llm_return_type/baml_tests__compiles__json_llm_return_type__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_map_literal/baml_tests__compiles__json_map_literal__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_parse_stringify_intrinsics/baml_tests__compiles__json_parse_stringify_intrinsics__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_to_from_string_composite_generic/baml_tests__compiles__json_to_from_string_composite_generic__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_to_from_string_concrete/baml_tests__compiles__json_to_from_string_concrete__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_to_from_string_generic_forwarding/baml_tests__compiles__json_to_from_string_generic_forwarding__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/json_to_from_string_three_level/baml_tests__compiles__json_to_from_string_three_level__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/lambda_advanced/baml_tests__compiles__lambda_advanced__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/lambda_basic/baml_tests__compiles__lambda_basic__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/lambda_fat_arrow/baml_tests__compiles__lambda_fat_arrow__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/lambda_field_access/baml_tests__compiles__lambda_field_access__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/lexical_scoping/baml_tests__compiles__lexical_scoping__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/literal_union_arithmetic/baml_tests__compiles__literal_union_arithmetic__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/literal_union_widening/baml_tests__compiles__literal_union_widening__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/llm_image_outputs/baml_tests__compiles__llm_image_outputs__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/llm_image_outputs/baml_tests__compiles__llm_image_outputs__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/llm_parse_catchable_parse_error/baml_tests__compiles__llm_parse_catchable_parse_error__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/llm_parse_catchable_parse_error/baml_tests__compiles__llm_parse_catchable_parse_error__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/method_explicit_type_args/baml_tests__compiles__method_explicit_type_args__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/namespaces_basic/baml_tests__compiles__namespaces_basic__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/namespaces_nested/baml_tests__compiles__namespaces_nested__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/namespaces_root_fallback/baml_tests__compiles__namespaces_root_fallback__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/namespaces_shadow/baml_tests__compiles__namespaces_shadow__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/namespaces_type_resolution/baml_tests__compiles__namespaces_type_resolution__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/numeric_invariance_ok/baml_tests__compiles__numeric_invariance_ok__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/numeric_literal_method_call/baml_tests__compiles__numeric_literal_method_call__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/o1_allowed_roles/baml_tests__compiles__o1_allowed_roles__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/optional_function_parameters/baml_tests__compiles__optional_function_parameters__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/optional_function_parameters/baml_tests__compiles__optional_function_parameters__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/paren_union_test/baml_tests__compiles__paren_union_test__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/parser_expressions/baml_tests__compiles__parser_expressions__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/parser_statements/baml_tests__compiles__parser_statements__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/patterns_class_destructure_namespaces/baml_tests__compiles__patterns_class_destructure_namespaces__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/patterns_new/baml_tests__compiles__patterns_new__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/reflect_type_of_user_generic/baml_tests__compiles__reflect_type_of_user_generic__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/retry_policy/baml_tests__compiles__retry_policy__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/scientific_notation_float/baml_tests__compiles__scientific_notation_float__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/stream_crossfile/baml_tests__compiles__stream_crossfile__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/stream_llm_inferred_typeargs/baml_tests__compiles__stream_llm_inferred_typeargs__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/stream_llm_inferred_typeargs/baml_tests__compiles__stream_llm_inferred_typeargs__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/string_methods/baml_tests__compiles__string_methods__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_basic/baml_tests__compiles__test_expr_basic__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_name_concat/baml_tests__compiles__test_expr_name_concat__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_throwing_body/baml_tests__compiles__test_expr_throwing_body__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_with_runner/baml_tests__compiles__test_expr_with_runner__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_old_and_new/baml_tests__compiles__test_old_and_new__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_raw_string_name/baml_tests__compiles__test_raw_string_name__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_with_not_keyword/baml_tests__compiles__test_with_not_keyword__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_basic/baml_tests__compiles__testset_basic__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_dynamic/baml_tests__compiles__testset_dynamic__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_nested/baml_tests__compiles__testset_nested__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_vibes_nested/baml_tests__compiles__testset_vibes_nested__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_vibes_nested/baml_tests__compiles__testset_vibes_nested__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_with_setup/baml_tests__compiles__testset_with_setup__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/top_level_header_comment/baml_tests__compiles__top_level_header_comment__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/top_level_let/baml_tests__compiles__top_level_let__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/type_annotation/baml_tests__compiles__type_annotation__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/type_builder_errors/baml_tests__compiles__type_builder_errors__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/type_builder_test/baml_tests__compiles__type_builder_test__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/anyfunction/baml_tests__diagnostic_errors__anyfunction__01_lexer__bans.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/anyfunction/baml_tests__diagnostic_errors__anyfunction__01_lexer__coercion.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/anyfunction/baml_tests__diagnostic_errors__anyfunction__02_parser__bans.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/anyfunction/baml_tests__diagnostic_errors__anyfunction__02_parser__coercion.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/anyfunction/baml_tests__diagnostic_errors__anyfunction__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/anyfunction/baml_tests__diagnostic_errors__anyfunction__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/anyfunction/baml_tests__diagnostic_errors__anyfunction__05_diagnostics.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/anyfunction/baml_tests__diagnostic_errors__anyfunction__10_formatter__bans.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/anyfunction/baml_tests__diagnostic_errors__anyfunction__10_formatter__coercion.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/engine/baml_tests__engine__tests__optional_dropping_adapter_preserves_source_defaults_bytecode.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/src/compiler2_tir/snapshots/baml_tests__compiler2_tir__phase5__snapshot_baml_package_items.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded_unoptimized.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_textual.snapis excluded by!**/*.snap
📒 Files selected for processing (26)
baml_language/crates/baml_builtins2/baml_std/baml/core.bamlbaml_language/crates/baml_builtins2/baml_std/reflect/reflect.bamlbaml_language/crates/baml_compiler2_ast/src/lower_expr_body.rsbaml_language/crates/baml_compiler2_emit/src/emit.rsbaml_language/crates/baml_compiler2_emit/src/lib.rsbaml_language/crates/baml_compiler2_mir/src/builder.rsbaml_language/crates/baml_compiler2_mir/src/ir.rsbaml_language/crates/baml_compiler2_mir/src/lower.rsbaml_language/crates/baml_compiler2_mir/src/pretty.rsbaml_language/crates/baml_compiler2_tir/src/infer_context.rsbaml_language/crates/baml_compiler2_tir/src/inference.rsbaml_language/crates/baml_compiler2_tir/src/interfaces/impl_rules.rsbaml_language/crates/baml_compiler_diagnostics/src/diagnostic.rsbaml_language/crates/baml_compiler_parser/src/parser.rsbaml_language/crates/baml_compiler_syntax/src/ast.rsbaml_language/crates/baml_lsp2_actions/src/check.rsbaml_language/crates/baml_tests/projects/compiles/anyfunction_reflect/main.bamlbaml_language/crates/baml_tests/projects/diagnostic_errors/anyfunction/bans.bamlbaml_language/crates/baml_tests/projects/diagnostic_errors/anyfunction/coercion.bamlbaml_language/crates/baml_tests/tests/reflect_call_any.rsbaml_language/crates/baml_type/src/normalize.rsbaml_language/crates/baml_type/src/normalize/tests.rsbaml_language/crates/bex_vm/src/lib.rsbaml_language/crates/bex_vm/src/package_baml/mod.rsbaml_language/crates/bex_vm/src/package_reflect/mod.rsbaml_language/crates/bex_vm/src/vm.rs
…teral key CodeRabbit findings on #4099: - function_callable_signature: a stored signature slot that does not realize (a generic's TypeVar, a symbolic projection) erases to unknown for that slot instead of dropping the whole callable, so reflect.signature / reflect.call_any work on generic function values - parser: object literals accept throws as an unquoted field key (Signature { throws: ... }), completing the field-name carve-out
# Conflicts: # baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded.snap # baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded_unoptimized.snap
…ignature Per review: the Signature/call_any named-args field is opts (not kwargs); the error-channel field is errors, dropping the throws-as-field-name carve-outs entirely (member access, field decls, and object-literal keys all reverted to the pre-existing keyword rules); Arg loses its always-null docstring; Signature gains the function's own docstring, threaded as a new borsh field on the runtime Function object (bex_cache FORMAT_VERSION 2). Also: the engine's call_callable now accepts the pooled GenericFunction wrapper (fallout from the function-value heap unification), and the canary merge's bytecode-display snapshots are regenerated.
A positional parameter with no recorded name (a host callable from a language without parameter-name introspection) reports the $argN placeholder for its position instead of null. $ cannot appear in a user identifier, so a placeholder can never collide with a declared parameter or named-argument key; nameless optionals stay excluded from opts (nothing to pass them by), so placeholders never enter by-name matching.
Binary size checks passed✅ 7 passed
Generated by |
⏭️ Performance benchmarks were skippedPerf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to To run them on this PR, do any of the following, then push a commit (or re-run CI):
|
- lower_lambda: one lower_sig_ty helper for param/return/throws annotations (was an inlined ScopeCtx duplicate); param names/defaults built as direct projections instead of parallel vecs - reflect natives: standard RealizedTy::unknown()/string() constructors replace hand-rolled ones; unreachable post-arity-check guard collapsed - vm: coarse-truth rationale documented once on function_callable_signature, cross-referenced elsewhere - normalize: covariant-pin lookup folded into one .any() predicate - tests: bare-AnyFunction dispatch test folded into the generic-callable test, non-throwing signature assert folded into the bound-method test, and the two diagnostic corpus files merged into one (the project-wide diagnostics snapshot already combined them); all behaviors keep a test Net -123 lines, no behavior change.
Not the qualified path: `greet`, `bump`, `println`. Also adapts the reflect native to canary's runtime type-algebra rework (#4046), where the VM itself is the `TypeContext` and `RuntimeTypeContext` is gone.
Adding a native to a stdlib package should be one edit to the package's .baml plus the implementation it demands. The codegen already gave the baml package that property; reflect hand-rolled a string match that nothing kept in sync. Three changes make the generator package-generic: - extract/codegen take the package: extract_native_builtins_for and generate_native_trait_for emit that package's BamlPackage<Pascal> root trait and prefix-stripping dispatcher. The media helpers now index segments from the end, so they need no package knowledge at all. - generated identifiers are raw-escaped for Rust keywords, so a BAML field named "type" (reflect.Arg) emits a raw identifier instead of failing to parse. Panic text keeps the BAML spelling. - package_reflect implements the generated BamlPackageReflect and builds every instance through the generated copy:: structs, so a field added to reflect.baml is a compile error until the native supplies it (the positional alloc_instance vecs are gone). reflect.signature/call_any declare their VM needs as //baml:mut_vm, //baml:fallible, //baml:may_yield directives, the same contract the baml package uses.
attach_builtins had a hand-written if/else chain over package prefixes, plus a second hand-maintained prefix list for the missing-native check. One VM_NATIVE_PACKAGES table now drives both, so adding a package is a single entry here alongside its build.rs generation. reflect joins the fail-fast set: the old exemption claimed reflect.type_of needed it, but an intrinsic never produces a function object (emit skips it), so a missing reflect native is now a load error like any other.
Follow-up to BoundaryML#4099, which made `baml_builtins2_codegen` package-generic and moved `reflect` onto it. `boundary` was the last package still hand-wiring its natives. ## What it was ```rust pub fn get_native_fn(path: &str) -> Option<NativeFunction> { match path.strip_prefix("boundary.")? { "id" => Some(id::new), "id.current" => Some(id::current), "LocalId.capture" => Some(id::capture), _ => None, } } ``` Nothing kept that in sync with the `.baml` declarations: adding a `$rust_function` and forgetting an arm gave a runtime lookup miss, not a build error. Each native also hand-rolled the boilerplate the generated glue already writes: arity checks, argument conversion, and the `Result` -> `NativeCallResult` match. ## What it is now `boundary` generates its `BamlPackageBoundary` / `BamlNamespaceId` / `BamlClassLocalId` hierarchy like `baml` and `reflect` (three lines in `bex_vm/build.rs`), so: - the three natives are required trait methods, and a declared `$rust_function` without an implementation is a compile error; - arguments arrive converted, so `LocalId.capture` takes `Option<bool>` triples instead of unpacking raw `Value`s, and the hand-written `optional_bool` helper is deleted; - the `LocalId` constructor builds through the generated `copy::LocalId` struct instead of a positional `alloc_instance(vec![...])`; - `VM_NATIVE_PACKAGES` now points every package at a generated dispatcher, so no entry in it can drift. ## Scope I checked the other stdlib packages: `log` is entirely `$compiler_intrinsic` (no natives), and `assert` and `testing` declare none, so `boundary` was the only remaining offender. Net +10 lines (the generation loop entry and trait scaffolding, minus the deleted dispatch and glue). Verified: `bex_vm` + `baml_tests` 2929 passing, `baml_cli` + `bex_engine` 976 passing, clippy clean. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Updated the Boundary runtime package to use the same generated native-function dispatch as other standard-library packages. * Improved handling of Boundary IDs and local ID capture through typed interfaces. * Preserved local ID capture behavior while simplifying argument handling and state management. * Added generated Boundary native-function support to the build process. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
# Conflicts: # baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____06_codegen.snap # baml_language/crates/bex_vm/src/type_match.rs
Implements the AnyFunction-only portion of BEP-062 (Function Interfaces). Excluded by design: tuples, named tuples, the
Functionbuiltin, spread/rest, andreflect.call.Surface
baml.AnyFunctionvia a derived rule in the subtype engine (works identically for the compiler and the VM's runtime context); pins are covariant.implements baml.AnyFunctionis E0153;extends baml.AnyFunctionbounds are E0154.call_anyR/E infer from the argument's pins, so a pinned tool map gets typed results and an exhaustive catch; a bareAnyFunctiondegrades tounknown/throws unknown. Absent kwargs fire the callee's own defaults (OMITTED_ARGprologue); the callee's typed throw propagates asthrows E.Arg.docstringis always null for now: the compiler does not record parameter docstrings yet; the field keeps tool-schema renderers shape-stable.Internals of note
GenericFunctionwrapper (identity stays pointer-stable), so a rawObject::Functionis never a data value. Non-function global item reads (clients, top-level lets) split off asConstant::GlobalItem-> plainLoadGlobal.lower_lambdanow recordsmir::RuntimeSignature, and one emit path (apply_signature_metadata) stamps both lambdas and top-level declarations.throwsis now valid as a field/member name (sig.throws), following the existingctx.clientcontextual-keyword pattern.load_global->load_constfor function references, andconst fn->const itemin MIR pretty for non-function items.Known follow-ups
-> AnyFunction(pre-existing: plain arrow returns are not rejected either).is-narrowing to concrete arrow types stays coarse (blocked on the void/never convention FIXME; reflect natives normalize it locally).call_anyare untested territory.Summary by CodeRabbit
baml.AnyFunctioninterface with typedReturns/Throwspins.reflect.signatureandreflect.call_any, including reconstructedargs/opts,$argNpositional support, defaults handling, and dispatch for lambdas and bound methods.reflect.signature.AnyFunctionusage (E0153/E0154) and runtimereflect.InvalidArgumentErrorwith expected-vs-got details.