BoundaryML/baml · error

expressions that evaluate to functions are not supported yet

Error message

expressions that evaluate to functions are not supported yet

What it means

BAML function-call compilation only supports calling a function by name (an identifier expression). If the callee expression is anything else — an arbitrary expression that evaluates to a function value — the code generator panics because first-class function values are not yet supported in this compiler path. Note the interpreter (THIR interpret) does support function values, so this is a codegen-only limitation.

Source

Thrown at engine/baml-compiler/src/codegen.rs:1248

                    self.compile_expression(value);
                }

                for (key, _) in pairs {
                    self.emit_string_literal(key);
                }

                self.emit(Instruction::AllocMap(pairs.len()));
            }

            thir::Expr::Call {
                func,
                args,
                type_args,
                ..
            } => {
                let name = match func.as_ref() {
                    thir::Expr::Var(name, _) => name,
                    _ => panic!("expressions that evaluate to functions are not supported yet"),
                };

                // Push the function onto the stack
                if let Some(&index) = self.globals.get(name) {
                    self.emit(Instruction::LoadGlobal(index));
                } else {
                    panic!("undefined function: {name}");
                }

                // Push the arguments onto the stack
                for arg in args {
                    self.compile_expression(arg);
                }

                // Type parameter. TODO: Generic way of handling this?
                if name == "baml.fetch_as" {
                    let type_index = self.objects.insert(Object::BamlType(type_args[0].clone()));
                    let const_index = self.add_constant(Value::Object(type_index));

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Call the function directly by its identifier name instead of via an intermediate expression
  2. Bind the result differently: call the function where its name is in scope rather than passing/deriving the callee dynamically
  3. If you need dynamic dispatch, use explicit branching (if/else calling named functions)
  4. Track BAML compiler releases for first-class function support; this is an explicit 'not supported yet' limitation

Example fix

// before
let f = my_function
f(args)
// after
my_function(args)
Defensive patterns

Strategy: validation

Validate before calling

fn validate_call_target(expr: &Expr) -> Result<(), String> {
    match expr { Expr::Var(_) => Ok(()), _ => Err("callee must be a named function identifier".into()) }
}

Type guard

fn is_named_callee(expr: &Expr) -> bool { matches!(expr, Expr::Var(_, _)) }

Prevention

When it happens

Trigger: Compiling a Call expression whose func field is not Expr::Var, e.g. calling the result of an expression like (get_fn())(...), calling a function stored in a variable, or invoking a method expression directly rather than via method-call syntax.

Common situations: Porting interpreter-friendly BAML (assigning functions to intermediate expressions) to compiled bytecode; attempting higher-order function calls in generated code; refactors that replaced a direct function name with an expression.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/a7801febaa248523. Report an issue: GitHub.