bigint#3526
Conversation
- Also bigint literals
`int` can always be widened to `bigint` automatically.
Arithmetic and bitwise operators similar to `int`.
These automatically will insert widening an `int` into a `bigint` before the operator instruction.
- Added variant to `BexExternalValue` - JSON serialization as decimal string - ffi serialization as hex string
For operations that produce Very Large `bigint` (around `2**(2**28)` or bigger) we throw a baml panic instead of doing it. So `bigint` in baml has an effective limit of being an `i268435456` (as opposed to `int` as `i64`) These include: - `bigint.pow` - `<<` for `bigint` Also fixed `>>` to saturate when shifting more than `usize::MAX` bits instead of erroring
- Extract `bigint` for builtin codegen - Python literals don't have `n` suffix
- Assignment statement - Assignment with optional chaining - Correctly handle type aliases
- bigint constants should be emitted through the `Object` constants path - Add `to_json` for `bigint` - `bigint` x `float` operations are not permitted
- `123N` will tell you to use lowercase - `12.3n` will tell you that bigints must be integers
We can also widen `int` to `bigint?` or other union-like things that include `bigint` (no widening if the union contains `int`)
|
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 engine-side BigInt conversion/coercion helpers and a full package_baml Bigint runtime implementation exposing methods (parse, pow, ilog, isqrt, random, etc.), with allocation/bit-size guards and error mapping into VM panics/errors. ChangesBigint Engine & Builtin
Sequence DiagramsequenceDiagram
participant Host
participant BexEngine
participant BexVm
participant BigintBuiltin
Host->>BexEngine: call function with external value (int/bigint)
BexEngine->>BexEngine: coerce_arg_to_declared_type(...)
BexEngine->>BexVm: convert_external_to_vm_value(coerced)
BexVm->>BigintBuiltin: invoke builtin method (pow/parse/...)
BigintBuiltin->>BexVm: alloc_bigint / possible VmPanic
BexVm->>BexEngine: convert_heap_ptr_to_external_with_type(Object::Bigint)
BexEngine->>Host: return coerced external Bigint
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
✨ Finishing Touches🧪 Generate unit tests (beta)
|
Binary size checks failed❌ 2 violations · ✅ 5 passed
Details & how to fixViolations:
Add/update baselines:
[artifacts.bridge_wasm]
file_bytes = 12691923
gzip_bytes = 3638234
[artifacts.bridge_cffi]
file_bytes = 17864952
stripped_bytes = 17864944
gzip_bytes = 6666116Generated by |
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
baml_language/crates/bridge_ctypes/src/value_decode.rs (1)
65-77:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInclude bigint in the default scalar union type.
Line [32] now decodes
InboundValueVariant::BigintValuetoBexExternalValue::Bigint, butdefault_scalar_union_ty()(Line [69]–Line [76]) doesn’t include bigint. That can mislabel inferred list/map value types and break downstream type handling for untyped inbound containers.🤖 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/bridge_ctypes/src/value_decode.rs` around lines 65 - 77, default_scalar_union_ty() omits the bigint variant, but inbound decoding produces InboundValueVariant::BigintValue -> BexExternalValue::Bigint; update default_scalar_union_ty() to include a Ty::Bigint { attr: d.clone() } entry in the Vec so bigint is treated as part of the "any scalar" union (preserve using the same TyAttr `d` and follow the pattern used for Int/Float/String/Bool/Uint8Array/Null).baml_language/sdks/python/rust/codegen_python/src/translate_ty.rs (1)
273-298:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd test cases for the new bigint type and literal.
The test suite
translate_ty_covers_phase_g3_matrixis meant to comprehensively cover allTyvariants, but it's missing cases for the newly addedTy::BigintandTy::Literal(Literal::Bigint(_)).📋 Suggested test cases to add
Case { + label: "bigint", + ty: Ty::Bigint, + ctx: ctx(&["lorem"]), + expected: "int", + }, + Case { + label: "literal bigint", + ty: Ty::Literal(Literal::Bigint("123456789012345678901234567890".to_string())), + ctx: ctx(&["lorem"]), + expected: "typing.Literal[123456789012345678901234567890]", + }, + Case { label: "int", ty: Ty::Int,As per coding guidelines, prefer writing Rust unit tests where possible and always run
cargo test --libafter changing Rust code.🤖 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/sdks/python/rust/codegen_python/src/translate_ty.rs` around lines 273 - 298, The test suite translate_ty_covers_phase_g3_matrix is missing coverage for the new AST variants Ty::Bigint and literal bigint forms (Literal::Bigint(_)); add unit test cases that construct Ty::Bigint and Ty::Literal(Literal::Bigint(...)) (or the codepath that produces those Ty variants) and include them in the phase G3 matrix so check_exhaustive (in translate_ty.rs) sees these variants; ensure tests assert translation/roundtrip behavior consistent with other entries and run cargo test --lib to verify.
🧹 Nitpick comments (8)
baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs (1)
251-251: ⚡ Quick winAdd a direct unit test for
TypeExpr::Bigintlowering.This new primitive branch is small but easy to regress; a focused local test asserting
TypeExpr::Bigintlowers toTy::Primitive(PrimitiveType::Bigint, ...)would lock behavior in.As per coding guidelines "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/baml_compiler2_tir/src/lower_type_expr.rs` at line 251, Add a focused unit test that constructs a TypeExpr::Bigint and passes it to the existing lowering function (e.g., lower_type_expr or the Lower::lower_type_expr API used in this module) and assert the result equals Ty::Primitive(PrimitiveType::Bigint, TyAttr::default()); place the test in this crate’s unit tests (same module or tests mod) so it exercises the exact branch added for TypeExpr::Bigint and prevents regressions of the PrimitiveType::Bigint lowering behavior.baml_language/crates/baml_compiler2_tir/src/normalize.rs (1)
234-235: ⚡ Quick winAdd bigint-focused subtype regression tests in this module.
Please add direct tests for
int <: bigint,bigint !<: int,Literal(Int) <: bigint, andLiteral(Bigint) <: bigintto keep the new widening rules stable.As per coding guidelines "Prefer writing Rust unit tests over integration tests where possible".
Also applies to: 241-243, 407-407
🤖 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_compiler2_tir/src/normalize.rs` around lines 234 - 235, Add unit tests in this module that assert the new numeric-widening subtype relations for StructuralTy: create tests verifying (1) StructuralTy::Int is a subtype of StructuralTy::Bigint, (2) StructuralTy::Bigint is NOT a subtype of StructuralTy::Int, (3) Literal(Int) is a subtype of StructuralTy::Bigint, and (4) Literal(Bigint) is a subtype of StructuralTy::Bigint; call the same internal subtype-checking function used elsewhere in this file (the normalize/rules function that handles StructuralTy variants) and use assert!(is_subtype(...)) or assert!(!is_subtype(...)) accordingly, giving each test a descriptive name (e.g., int_is_subtype_of_bigint, bigint_not_subtype_of_int, literal_int_subtype_of_bigint, literal_bigint_subtype_of_bigint) so they run as unit tests in this module.baml_language/crates/baml_compiler_lexer/src/tokens.rs (1)
1005-1039: 💤 Low valueComprehensive test coverage for bigint literals.
The test thoroughly covers valid bigint literals and important edge cases. One optional enhancement: consider adding tests that document how malformed bigint literals (e.g.,
123N,1.23n) are tokenized, even though diagnostics are emitted by the parser.📋 Optional: Document malformed bigint tokenization
// Malformed bigint literals (uppercase N) — lexer emits separate tokens, // parser diagnoses the error assert_eq!( lex_no_whitespace("123N"), vec![TokenKind::IntegerLiteral, TokenKind::Word] ); // Malformed bigint literals (float with n suffix) — lexer emits separate tokens assert_eq!( lex_no_whitespace("1.23n"), vec![TokenKind::FloatLiteral, TokenKind::Word] );🤖 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_compiler_lexer/src/tokens.rs` around lines 1005 - 1039, Add assertions covering malformed bigint tokenization in the bigint tests: inside or alongside the existing lex_bigint_literal test, add cases that call lex_no_whitespace("123N") and assert it returns [TokenKind::IntegerLiteral, TokenKind::Word], and call lex_no_whitespace("1.23n") and assert it returns [TokenKind::FloatLiteral, TokenKind::Word]; reference the existing lex_no_whitespace helper and TokenKind variants (IntegerLiteral, FloatLiteral, Word) so the lexer behavior is documented without changing lexer logic.baml_language/crates/bex_heap/src/tlab.rs (1)
202-207: ⚡ Quick winAdd a unit test for
alloc_bigintto lock in object-shape behavior.This new allocator is straightforward, but adding a local unit test (matching other
alloc_*tests in this file) would prevent regressions in variant wrapping and heap write/read flow.As per coding guidelines "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_heap/src/tlab.rs` around lines 202 - 207, Add a local unit test for alloc_bigint mirroring the existing alloc_* tests: construct a num_bigint::BigInt (e.g., BigInt::from(123u32)), call tlab.alloc_bigint(value.clone()), then read the allocated object back from the heap (using the same helper/read method used by other tests) and assert it matches Object::Bigint(Arc::new(value)) or otherwise compare the inner BigInt for equality; ensure the test lives in the same module/tests block as the other alloc_* tests so it exercises the allocator path and the Arc-wrapping/read semantics for alloc_bigint.baml_language/crates/bex_sap/src/deserializer/coercer/coerce_primitive.rs (1)
274-513: ⚡ Quick winAdd focused unit tests for the new bigint coercion helpers.
parse_bigint_from_number_text,bigint_from_finite_f64, andBigintTy::{coerce,try_cast}introduce nuanced numeric behavior; unit tests here would materially improve confidence on boundary cases (huge ints, exponent/decimal rejection intry_cast, float rounding paths, and string parsing variants).As per coding guidelines "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_sap/src/deserializer/coercer/coerce_primitive.rs` around lines 274 - 513, Add focused unit tests covering parse_bigint_from_number_text, bigint_from_finite_f64, BigintTy::coerce, and BigintTy::try_cast: test parse_bigint_from_number_text rejects numbers with '.' or 'e'/'E' and parses very large integer strings; test bigint_from_finite_f64 for round-half-away-from-zero behavior on positive/negative .5 boundaries, for finite huge floats beyond i128 that must be parsed via decimal formatting, and for NaN/infinity returning None; for BigintTy::coerce add tests for Number variants (i64/u64 path, arbitrary-precision via Number text, float-to-bigint with flags and error on non-finite), String inputs (integer strings, comma-trim/decimal/fraction variants that round, in-progress CompletionState handling), Array->singular coercion, and for try_cast verify it accepts exact integer Numbers only (rejects decimals/exponents and floats) and respects CompletionState/AttrLiteral branches. Use the existing helpers and type constructors from the module to build minimal ParsingContext/value fixtures.baml_language/crates/bridge_ctypes/src/handle_table.rs (1)
296-302: ⚡ Quick winAdd explicit bigint rejection coverage in
try_from_rejects_primitives.Since
BexExternalValue::Bigint(_)was newly added to the rejection list (Line [96]), add an assertion for it in this test to lock in behavior and prevent accidental re-allowing.🤖 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/bridge_ctypes/src/handle_table.rs` around lines 296 - 302, The test try_from_rejects_primitives should also assert that CffiHandleTableEntry::try_from rejects BexExternalValue::Bigint; add an assertion in that function like assert!(CffiHandleTableEntry::try_from(BexExternalValue::Bigint(...)).is_err()) so the new rejection of Bigint (added near the match on BexExternalValue) is covered and cannot be accidentally reverted.baml_language/crates/sys_llm/src/types/output_format.rs (1)
695-695: ⚡ Quick winAdd direct unit coverage for bigint rendering paths.
Please add tests for
Ty::Bigintauto rendering andLiteralValue::Bigintrendering (123n, negative values) to lock this behavior down.As per coding guidelines:
**/*.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/sys_llm/src/types/output_format.rs` at line 695, Add unit tests in the same crate (inside a #[cfg(test)] mod tests block) that assert the rendering behavior for both Ty::Bigint auto-rendering and LiteralValue::Bigint formatting; specifically create tests that construct a Ty::Bigint and verify its rendered string matches the expected auto-render output, and create tests that construct LiteralValue::Bigint for positive (e.g., 123) and negative values and assert the renderer produces "123n" and "-123n" respectively. Place the tests near the code in output_format.rs (or in its test module), use the existing render/formatting functions used by the file (referencing LiteralValue::Bigint and Ty::Bigint) and use assert_eq! to lock the behavior. Ensure tests are unit tests (not integration) per guidelines.baml_language/crates/baml_tests/projects/compiles/bigint_arith/bigint_arith.baml (1)
5-43: ⚡ Quick winAdd mixed
bigint/intarithmetic cases to lock in implicit widening opcode coverage.Current tests only exercise
bigint-bigintoperands. Adding mixed operands (e.g.,1n + 2,1n << 4) helps prevent regressions in theint -> bigintwidening path.Suggested additions
function AddBigints() -> bigint { 2n + 3n } +function AddBigintIntMixed() -> bigint { + 2n + 3 +} + ... function ShlBigints() -> bigint { 1n << 4n } +function ShlBigintIntMixed() -> bigint { + 1n << 4 +}🤖 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/compiles/bigint_arith/bigint_arith.baml` around lines 5 - 43, Add test cases that mix bigint and int operands to cover implicit widening paths: create functions like AddBigintInt() -> bigint (e.g., 1n + 2), AddIntBigint() -> bigint (e.g., 1 + 2n), ShlBigintInt() -> bigint (e.g., 1n << 4), ShrBigintInt() -> bigint (e.g., 256n >> 4), and other mixed variants for Sub, Mul, Div, Mod, BitAnd, BitOr, BitXor using existing function naming pattern (e.g., SubBigintInt, MulIntBigint) so the compiler exercises int -> bigint widening and opcode coverage for mixed operands.
🤖 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 1988-1992: parse_type_primary accepts BigintLiteral but several
upstream guards/disambiguators still exclude TokenKind::BigintLiteral so valid
big-int inputs never reach that branch; update the predicate/guard functions
that test token starts to include BigintLiteral (e.g. the functions or checks
that currently gate field/param type start, pattern atom start, generic-arg
disambiguation and config-expression detection) instead of excluding it — find
the checks that call self.at(TokenKind::...) or use helper predicates like
is_start_of_type / is_start_of_pattern_atom / is_start_of_generic_arg /
is_start_of_config_expr and add TokenKind::BigintLiteral as an allowed starter
(or remove the explicit exclusion) so the existing parse_type_primary branch for
BigintLiteral is reachable.
In `@baml_language/crates/baml_compiler2_ast/src/lower_expr_body.rs`:
- Around line 397-400: The "is" token fallback branch that currently handles
bare INTEGER_LITERAL and FLOAT_LITERAL must also handle BIGINT_LITERAL so
scrutinees like "1n is ..." don't lower to Expr::Missing; add a case matching
SyntaxKind::BIGINT_LITERAL (the same branch where INTEGER_LITERAL/FLOAT_LITERAL
are handled around the "is" fallback) and call
crate::parse_bigint_literal_token(token.text()) and wrap with
self.alloc_expr(Expr::Literal(Literal::Bigint(value)), span) mirroring the
existing INTEGER/FLOAT handling (use the same span and allocation pattern used
in lower_expr_body.rs).
In `@baml_language/crates/baml_compiler2_mir/src/lower.rs`:
- Around line 3372-3383: The code in lower_call_arg_operands currently only
populates param_bigint_flags when callee_func_loc_for_call sees an
AstExpr::Call, so OptionalCall forms (handled via lower_optional_call →
lower_call) never get bigint param flags and miss injecting IntToBigint
coercions; update the resolution logic so that callee_func_loc_for_call (or an
added helper used by lower_call_arg_operands) recognizes AstExpr::OptionalCall
and extracts the inner call/callee FunctionLoc the same way as AstExpr::Call,
then build param_bigint_flags from that FunctionLoc so lower_call_arg_operands
will insert IntToBigint conversions for optional-call arguments as well (apply
same fix at the other occurrence around lines 4486-4495).
- Around line 3145-3167: The current widening branch uses
self.value_is_natural_int(value) which returns false for captured single-segment
paths so captured int RHS in closures bypasses bigint widening; update the
condition that sets rhs to also treat captured single-segment path expressions
as natural ints by checking the AST form (e.g., match Expr::Path with a single
segment and a captured/local flag) or otherwise querying the capture info for
`value` before falling back to self.lower_to_operand; adjust the logic near
dest_widens_int_to_bigint, the use of self.value_is_natural_int(value), and the
code that calls self.lower_expr/lower_to_operand (symbols:
dest_widens_int_to_bigint, value_is_natural_int, lower_expr, lower_to_operand,
Place::local) so that captured single-segment paths are coerced via the
Int->Bigint temp sequence just like explicit natural-int literals/exprs.
- Around line 3383-3406: The code currently re-lowers each signature param via
lower_type_expr_in_ns with an empty generic_params list, losing call-site
instantiations (so T instantiated as bigint isn't seen); instead use the
already-instantiated parameter type for each sig.params entry coming from the
call-site (i.e., apply the call's generic substitutions/instantiation rather
than generic_params = &[]) before passing the type through
resolved_aliases.convert and into Self::dest_widens_int_to_bigint; in practice
replace the re-lowering step that calls lower_type_expr_in_ns with logic that
obtains the instantiated param type (or passes the call's generic substitutions
into lower_type_expr_in_ns) so the widening decision uses the concrete
instantiated type.
In `@baml_language/crates/baml_type/src/lib.rs`:
- Around line 116-118: The new Ty::Bigint variant was added but
Ty::is_primitive() was not updated, so add Bigint to the primitive
classification: update the match/if in Ty::is_primitive() to return true for
Ty::Bigint alongside the other primitive variants (refer to the Ty::Bigint enum
variant and the Ty::is_primitive() function to locate the change), ensuring
bigint follows the same primitive-gated code paths as other primitive types.
In `@baml_language/crates/bex_engine/src/conversion.rs`:
- Around line 681-682: The match arm incorrectly treats Object::Bigint(_) as
non-participating in union-member resolution; update the match in conversion
logic in conversion.rs so Object::Bigint(_) is handled alongside other
participating numeric/string types (i.e., move Bigint into the branch that
attempts union-member resolution) and also add corresponding bigint handling in
the VM→external type matching code path (the external type matcher used by the
VM-to-external union conversion) so bigint values map to the correct external
union member instead of triggering TypeMismatch.
In `@baml_language/crates/bex_vm_types/src/bytecode.rs`:
- Around line 302-310: The comment for ShlBigint is out of date: instead of
saying the VM raises VmBamlError::InvalidArgument "until Phase 12 wires up a
dedicated AllocFailure panic", update the doc to reflect the current runtime
contract—state that if the right operand (shift count) does not fit in a usize
the VM will raise/propagate an AllocFailure panic (or whatever exact
AllocFailure mechanism is now implemented) rather than InvalidArgument; update
both occurrences in the ShlBigint comment text and remove the temporary Phase 12
wording so the docs match the implemented behavior.
In `@baml_language/crates/bex_vm/src/vm.rs`:
- Around line 3468-3490: The right-shift handler currently treats any
non-`usize` RHS as a saturation case (so negative counts like `-1n` saturate
instead of erroring); change the logic that computes `shift_opt` to explicitly
reject negative BigInt RHS values (check `rb.sign() == num_bigint::Sign::Minus`
and return an error/VM trap like the left-shift path does) before attempting
`usize::try_from(...)`, update the analogous right-shift code path (and the
similar handler referenced at lines ~7626-7647) to mirror `ShlBigint`’s
negative-count rejection, and add a unit test asserting that `>> -1n` produces
the expected failure (write a Rust unit test, not an integration test) to verify
the behavior; use the existing helpers `get_object`, `alloc_bigint`, and the VM
error/trap mechanism when implementing the rejection.
In `@baml_language/crates/bridge_ctypes/src/value_decode.rs`:
- Around line 291-294: The test currently builds a local string `message` and
asserts its length, but it should assert the actual error text to detect payload
leakage; replace the existing length check with an assertion on
`err.to_string()` (e.g., assert!(err.to_string().len() < 200)) so the test
verifies the real error produced by the code path that uses `blob_len` rather
than the locally constructed `message`. Ensure `err` is in scope and remove or
ignore the unused `message` variable if no longer needed.
In `@baml_language/crates/bridge_ctypes/src/value_encode.rs`:
- Around line 30-33: Runtime bigint serialization (BexExternalValue::Bigint ->
BamlValueVariant::BigintValue) currently emits hex (format!("{bi:x}")) while
metadata uses decimal (n.to_string()), causing an encoding inconsistency; make
them consistent by changing the runtime path in value_encode.rs to emit a
decimal string (use bi.to_string()) and add/adjust the adjacent comment to note
the temporary inconsistency and link to the Phase 10 bigint plan/TODO so future
coordinated changes handle both BexExternalValue::Bigint and the metadata path
that uses n.to_string().
In `@baml_language/crates/sys_llm/src/types/output_format.rs`:
- Line 429: The Ty::Bigint match arm currently returns a plain "bigint" string
and isn’t handled as a primitive-instruction under RenderSetting::Auto; change
the Ty::Bigint branch in the output formatting code so it follows the same path
as other numeric primitives (mirror the logic used for Ty::Int/Ty::Float) when
RenderSetting::Auto is active—i.e., produce the instruction-style prompt/output
used for primitives rather than the raw "bigint" token; update the Ty::Bigint
arm in the function that maps Ty -> string (the match containing Ty::Bigint) to
reuse the primitive/instruction formatting logic.
---
Outside diff comments:
In `@baml_language/crates/bridge_ctypes/src/value_decode.rs`:
- Around line 65-77: default_scalar_union_ty() omits the bigint variant, but
inbound decoding produces InboundValueVariant::BigintValue ->
BexExternalValue::Bigint; update default_scalar_union_ty() to include a
Ty::Bigint { attr: d.clone() } entry in the Vec so bigint is treated as part of
the "any scalar" union (preserve using the same TyAttr `d` and follow the
pattern used for Int/Float/String/Bool/Uint8Array/Null).
In `@baml_language/sdks/python/rust/codegen_python/src/translate_ty.rs`:
- Around line 273-298: The test suite translate_ty_covers_phase_g3_matrix is
missing coverage for the new AST variants Ty::Bigint and literal bigint forms
(Literal::Bigint(_)); add unit test cases that construct Ty::Bigint and
Ty::Literal(Literal::Bigint(...)) (or the codepath that produces those Ty
variants) and include them in the phase G3 matrix so check_exhaustive (in
translate_ty.rs) sees these variants; ensure tests assert translation/roundtrip
behavior consistent with other entries and run cargo test --lib to verify.
---
Nitpick comments:
In `@baml_language/crates/baml_compiler_lexer/src/tokens.rs`:
- Around line 1005-1039: Add assertions covering malformed bigint tokenization
in the bigint tests: inside or alongside the existing lex_bigint_literal test,
add cases that call lex_no_whitespace("123N") and assert it returns
[TokenKind::IntegerLiteral, TokenKind::Word], and call
lex_no_whitespace("1.23n") and assert it returns [TokenKind::FloatLiteral,
TokenKind::Word]; reference the existing lex_no_whitespace helper and TokenKind
variants (IntegerLiteral, FloatLiteral, Word) so the lexer behavior is
documented without changing lexer logic.
In `@baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs`:
- Line 251: Add a focused unit test that constructs a TypeExpr::Bigint and
passes it to the existing lowering function (e.g., lower_type_expr or the
Lower::lower_type_expr API used in this module) and assert the result equals
Ty::Primitive(PrimitiveType::Bigint, TyAttr::default()); place the test in this
crate’s unit tests (same module or tests mod) so it exercises the exact branch
added for TypeExpr::Bigint and prevents regressions of the PrimitiveType::Bigint
lowering behavior.
In `@baml_language/crates/baml_compiler2_tir/src/normalize.rs`:
- Around line 234-235: Add unit tests in this module that assert the new
numeric-widening subtype relations for StructuralTy: create tests verifying (1)
StructuralTy::Int is a subtype of StructuralTy::Bigint, (2) StructuralTy::Bigint
is NOT a subtype of StructuralTy::Int, (3) Literal(Int) is a subtype of
StructuralTy::Bigint, and (4) Literal(Bigint) is a subtype of
StructuralTy::Bigint; call the same internal subtype-checking function used
elsewhere in this file (the normalize/rules function that handles StructuralTy
variants) and use assert!(is_subtype(...)) or assert!(!is_subtype(...))
accordingly, giving each test a descriptive name (e.g.,
int_is_subtype_of_bigint, bigint_not_subtype_of_int,
literal_int_subtype_of_bigint, literal_bigint_subtype_of_bigint) so they run as
unit tests in this module.
In
`@baml_language/crates/baml_tests/projects/compiles/bigint_arith/bigint_arith.baml`:
- Around line 5-43: Add test cases that mix bigint and int operands to cover
implicit widening paths: create functions like AddBigintInt() -> bigint (e.g.,
1n + 2), AddIntBigint() -> bigint (e.g., 1 + 2n), ShlBigintInt() -> bigint
(e.g., 1n << 4), ShrBigintInt() -> bigint (e.g., 256n >> 4), and other mixed
variants for Sub, Mul, Div, Mod, BitAnd, BitOr, BitXor using existing function
naming pattern (e.g., SubBigintInt, MulIntBigint) so the compiler exercises int
-> bigint widening and opcode coverage for mixed operands.
In `@baml_language/crates/bex_heap/src/tlab.rs`:
- Around line 202-207: Add a local unit test for alloc_bigint mirroring the
existing alloc_* tests: construct a num_bigint::BigInt (e.g.,
BigInt::from(123u32)), call tlab.alloc_bigint(value.clone()), then read the
allocated object back from the heap (using the same helper/read method used by
other tests) and assert it matches Object::Bigint(Arc::new(value)) or otherwise
compare the inner BigInt for equality; ensure the test lives in the same
module/tests block as the other alloc_* tests so it exercises the allocator path
and the Arc-wrapping/read semantics for alloc_bigint.
In `@baml_language/crates/bex_sap/src/deserializer/coercer/coerce_primitive.rs`:
- Around line 274-513: Add focused unit tests covering
parse_bigint_from_number_text, bigint_from_finite_f64, BigintTy::coerce, and
BigintTy::try_cast: test parse_bigint_from_number_text rejects numbers with '.'
or 'e'/'E' and parses very large integer strings; test bigint_from_finite_f64
for round-half-away-from-zero behavior on positive/negative .5 boundaries, for
finite huge floats beyond i128 that must be parsed via decimal formatting, and
for NaN/infinity returning None; for BigintTy::coerce add tests for Number
variants (i64/u64 path, arbitrary-precision via Number text, float-to-bigint
with flags and error on non-finite), String inputs (integer strings,
comma-trim/decimal/fraction variants that round, in-progress CompletionState
handling), Array->singular coercion, and for try_cast verify it accepts exact
integer Numbers only (rejects decimals/exponents and floats) and respects
CompletionState/AttrLiteral branches. Use the existing helpers and type
constructors from the module to build minimal ParsingContext/value fixtures.
In `@baml_language/crates/bridge_ctypes/src/handle_table.rs`:
- Around line 296-302: The test try_from_rejects_primitives should also assert
that CffiHandleTableEntry::try_from rejects BexExternalValue::Bigint; add an
assertion in that function like
assert!(CffiHandleTableEntry::try_from(BexExternalValue::Bigint(...)).is_err())
so the new rejection of Bigint (added near the match on BexExternalValue) is
covered and cannot be accidentally reverted.
In `@baml_language/crates/sys_llm/src/types/output_format.rs`:
- Line 695: Add unit tests in the same crate (inside a #[cfg(test)] mod tests
block) that assert the rendering behavior for both Ty::Bigint auto-rendering and
LiteralValue::Bigint formatting; specifically create tests that construct a
Ty::Bigint and verify its rendered string matches the expected auto-render
output, and create tests that construct LiteralValue::Bigint for positive (e.g.,
123) and negative values and assert the renderer produces "123n" and "-123n"
respectively. Place the tests near the code in output_format.rs (or in its test
module), use the existing render/formatting functions used by the file
(referencing LiteralValue::Bigint and Ty::Bigint) and use assert_eq! to lock the
behavior. Ensure tests are unit tests (not integration) per guidelines.
🪄 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: 613e9e9c-7c65-43c9-b291-e488cee13f27
⛔ Files ignored due to path filters (102)
baml_language/Cargo.lockis excluded by!**/*.lockbaml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_package_listing.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_tir.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/__testing_std__/baml_tests__compiles____testing_std____06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__01_lexer__bigint_arith.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__02_parser__bigint_arith.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__05_diagnostics.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_arith/baml_tests__compiles__bigint_arith__10_formatter__bigint_arith.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__01_lexer__bigint_cmp.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__02_parser__bigint_cmp.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__05_diagnostics.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_cmp/baml_tests__compiles__bigint_cmp__10_formatter__bigint_cmp.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_literal/baml_tests__compiles__bigint_literal__01_lexer__bigint_literal.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_literal/baml_tests__compiles__bigint_literal__02_parser__bigint_literal.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_literal/baml_tests__compiles__bigint_literal__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_literal/baml_tests__compiles__bigint_literal__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_literal/baml_tests__compiles__bigint_literal__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_literal/baml_tests__compiles__bigint_literal__05_diagnostics.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/bigint_literal/baml_tests__compiles__bigint_literal__10_formatter__bigint_literal.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/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/event_system/baml_tests__compiles__event_system__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/is_operator/baml_tests__compiles__is_operator__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_fat_arrow/baml_tests__compiles__lambda_fat_arrow__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/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/test_expr_basic/baml_tests__compiles__test_expr_basic__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_basic/baml_tests__compiles__test_expr_basic__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_basic/baml_tests__compiles__test_expr_basic__04_tir.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__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_name_concat/baml_tests__compiles__test_expr_name_concat__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_name_concat/baml_tests__compiles__test_expr_name_concat__04_tir.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__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_throwing_body/baml_tests__compiles__test_expr_throwing_body__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_expr_throwing_body/baml_tests__compiles__test_expr_throwing_body__04_tir.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_old_and_new/baml_tests__compiles__test_old_and_new__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_old_and_new/baml_tests__compiles__test_old_and_new__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_old_and_new/baml_tests__compiles__test_old_and_new__04_tir.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__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_raw_string_name/baml_tests__compiles__test_raw_string_name__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_raw_string_name/baml_tests__compiles__test_raw_string_name__04_tir.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__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_with_not_keyword/baml_tests__compiles__test_with_not_keyword__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/test_with_not_keyword/baml_tests__compiles__test_with_not_keyword__04_tir.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__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_basic/baml_tests__compiles__testset_basic__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_basic/baml_tests__compiles__testset_basic__04_tir.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__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_dynamic/baml_tests__compiles__testset_dynamic__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_dynamic/baml_tests__compiles__testset_dynamic__04_tir.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__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_nested/baml_tests__compiles__testset_nested__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_nested/baml_tests__compiles__testset_nested__04_tir.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__03_hir.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__04_tir.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__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_with_setup/baml_tests__compiles__testset_with_setup__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/testset_with_setup/baml_tests__compiles__testset_with_setup__04_tir.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/diagnostic_errors/test_expr_name_type_error/baml_tests__diagnostic_errors__test_expr_name_type_error__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/test_expr_name_type_error/baml_tests__diagnostic_errors__test_expr_name_type_error__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/test_expr_with_runner/baml_tests__diagnostic_errors__test_expr_with_runner__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/test_expr_with_runner/baml_tests__diagnostic_errors__test_expr_with_runner__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/test_expr_wrong_runner/baml_tests__diagnostic_errors__test_expr_wrong_runner__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/test_expr_wrong_runner/baml_tests__diagnostic_errors__test_expr_wrong_runner__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/test_with_runner_ambiguity/baml_tests__diagnostic_errors__test_with_runner_ambiguity__03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/diagnostic_errors/test_with_runner_ambiguity/baml_tests__diagnostic_errors__test_with_runner_ambiguity__04_tir.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 (127)
baml_language/Cargo.tomlbaml_language/crates/baml_base/Cargo.tomlbaml_language/crates/baml_base/src/core_types.rsbaml_language/crates/baml_builtins2/baml_std/baml/bigint.bamlbaml_language/crates/baml_builtins2/src/lib.rsbaml_language/crates/baml_builtins2_codegen/src/codegen.rsbaml_language/crates/baml_builtins2_codegen/src/codegen_io.rsbaml_language/crates/baml_builtins2_codegen/src/extract.rsbaml_language/crates/baml_builtins2_codegen/src/types.rsbaml_language/crates/baml_codegen_types/src/symbols.rsbaml_language/crates/baml_codegen_types/src/ty.rsbaml_language/crates/baml_compiler2_ast/Cargo.tomlbaml_language/crates/baml_compiler2_ast/src/ast.rsbaml_language/crates/baml_compiler2_ast/src/lib.rsbaml_language/crates/baml_compiler2_ast/src/lower_expr_body.rsbaml_language/crates/baml_compiler2_ast/src/lower_type_expr.rsbaml_language/crates/baml_compiler2_emit/src/analysis.rsbaml_language/crates/baml_compiler2_emit/src/emit.rsbaml_language/crates/baml_compiler2_emit/src/pull_semantics.rsbaml_language/crates/baml_compiler2_emit/src/stack_carry.rsbaml_language/crates/baml_compiler2_hir/src/builder.rsbaml_language/crates/baml_compiler2_mir/Cargo.tomlbaml_language/crates/baml_compiler2_mir/src/ir.rsbaml_language/crates/baml_compiler2_mir/src/lower.rsbaml_language/crates/baml_compiler2_mir/src/optimize.rsbaml_language/crates/baml_compiler2_mir/src/pretty.rsbaml_language/crates/baml_compiler2_ppir/src/expand.rsbaml_language/crates/baml_compiler2_ppir/src/ty.rsbaml_language/crates/baml_compiler2_tir/src/builder.rsbaml_language/crates/baml_compiler2_tir/src/exhaustiveness.rsbaml_language/crates/baml_compiler2_tir/src/lower_type_expr.rsbaml_language/crates/baml_compiler2_tir/src/normalize.rsbaml_language/crates/baml_compiler2_tir/src/ty.rsbaml_language/crates/baml_compiler2_visualization/src/control_flow/from_ast.rsbaml_language/crates/baml_compiler_lexer/src/tokens.rsbaml_language/crates/baml_compiler_parser/src/parser.rsbaml_language/crates/baml_compiler_syntax/src/ast.rsbaml_language/crates/baml_compiler_syntax/src/syntax_kind.rsbaml_language/crates/baml_lsp2_actions/src/check.rsbaml_language/crates/baml_lsp2_actions/src/utils.rsbaml_language/crates/baml_project/src/client_codegen.rsbaml_language/crates/baml_tests/Cargo.tomlbaml_language/crates/baml_tests/projects/compiles/bigint_arith/bigint_arith.bamlbaml_language/crates/baml_tests/projects/compiles/bigint_cmp/bigint_cmp.bamlbaml_language/crates/baml_tests/projects/compiles/bigint_literal/bigint_literal.bamlbaml_language/crates/baml_tests/src/compiler2_tir/inference.rsbaml_language/crates/baml_tests/src/compiler2_tir/mod.rsbaml_language/crates/baml_tests/src/compiler2_tir/phase3a.rsbaml_language/crates/baml_tests/tests/bigints.rsbaml_language/crates/baml_tests/tests/classes.rsbaml_language/crates/baml_tests/tests/deep_copy.rsbaml_language/crates/baml_tests/tests/exceptions.rsbaml_language/crates/baml_tests/tests/for_loops.rsbaml_language/crates/baml_tests/tests/functions.rsbaml_language/crates/baml_tests/tests/if_else.rsbaml_language/crates/baml_tests/tests/match_basics.rsbaml_language/crates/baml_tests/tests/match_types.rsbaml_language/crates/baml_tests/tests/operators.rsbaml_language/crates/baml_tests/tests/optimization.rsbaml_language/crates/baml_tests/tests/soundness.rsbaml_language/crates/baml_tests/tests/watch.rsbaml_language/crates/baml_tests/tests/while_loops.rsbaml_language/crates/baml_type/Cargo.tomlbaml_language/crates/baml_type/src/lib.rsbaml_language/crates/baml_type/src/simplify_sap.rsbaml_language/crates/baml_type/src/typetag.rsbaml_language/crates/bex_engine/src/conversion.rsbaml_language/crates/bex_events/src/serialize.rsbaml_language/crates/bex_external_types/Cargo.tomlbaml_language/crates/bex_external_types/src/bex_external_value.rsbaml_language/crates/bex_heap/Cargo.tomlbaml_language/crates/bex_heap/src/accessor.rsbaml_language/crates/bex_heap/src/gc.rsbaml_language/crates/bex_heap/src/heap_debugger/real.rsbaml_language/crates/bex_heap/src/tlab.rsbaml_language/crates/bex_project/src/bex_lsp/multi_project/mod.rsbaml_language/crates/bex_sap/Cargo.tomlbaml_language/crates/bex_sap/src/baml_value.rsbaml_language/crates/bex_sap/src/deserializer/coercer/coerce_literal.rsbaml_language/crates/bex_sap/src/deserializer/coercer/coerce_primitive.rsbaml_language/crates/bex_sap/src/deserializer/coercer/coerce_ty.rsbaml_language/crates/bex_sap/src/deserializer/deserialize_flags.rsbaml_language/crates/bex_sap/src/deserializer/score.rsbaml_language/crates/bex_sap/src/deserializer/types.rsbaml_language/crates/bex_sap/src/jsonish/value.rsbaml_language/crates/bex_sap/src/sap_model/convert.rsbaml_language/crates/bex_sap/src/sap_model/from_literal.rsbaml_language/crates/bex_sap/src/sap_model/mod.rsbaml_language/crates/bex_sap/src/sap_model/test_macros.rsbaml_language/crates/bex_sap/src/sap_model/type_name.rsbaml_language/crates/bex_sap/src/tests/test_basics.rsbaml_language/crates/bex_sap/src/to_external.rsbaml_language/crates/bex_vm/Cargo.tomlbaml_language/crates/bex_vm/src/debug.rsbaml_language/crates/bex_vm/src/package_baml/bigint.rsbaml_language/crates/bex_vm/src/package_baml/json.rsbaml_language/crates/bex_vm/src/package_baml/mod.rsbaml_language/crates/bex_vm/src/package_baml/root.rsbaml_language/crates/bex_vm/src/package_baml/unstable.rsbaml_language/crates/bex_vm/src/vm.rsbaml_language/crates/bex_vm/tests/deep_equals_bigint.rsbaml_language/crates/bex_vm_types/Cargo.tomlbaml_language/crates/bex_vm_types/src/bytecode.rsbaml_language/crates/bex_vm_types/src/types.rsbaml_language/crates/bridge_ctypes/Cargo.tomlbaml_language/crates/bridge_ctypes/src/error.rsbaml_language/crates/bridge_ctypes/src/handle_table.rsbaml_language/crates/bridge_ctypes/src/value_decode.rsbaml_language/crates/bridge_ctypes/src/value_encode.rsbaml_language/crates/bridge_ctypes/types/baml_core/cffi/v1/baml_inbound.protobaml_language/crates/bridge_ctypes/types/baml_core/cffi/v1/baml_outbound.protobaml_language/crates/bridge_nodejs/tests/call_function.test.tsbaml_language/crates/bridge_nodejs/typescript_src/proto.tsbaml_language/crates/sys_jinja_types/src/evaluate_type/stmt.rsbaml_language/crates/sys_jinja_types/src/evaluate_type/types.rsbaml_language/crates/sys_llm/src/build_request/mod.rsbaml_language/crates/sys_llm/src/jinja/value_conversion.rsbaml_language/crates/sys_llm/src/types/output_format.rsbaml_language/crates/tools_onionskin/src/compiler.rsbaml_language/sdks/python/rust/codegen_python/src/leaf.rsbaml_language/sdks/python/rust/codegen_python/src/translate_ty.rsbaml_language/sdks/python/src/baml_core/cffi/v1/baml_inbound_pb2.pybaml_language/sdks/python/src/baml_core/cffi/v1/baml_inbound_pb2.pyibaml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pybaml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pyibaml_language/sdks/python/src/baml_core/proto.pybaml_language/sdks/python/tests/test_bigint.py
👮 Files not reviewed due to content moderation or server errors (1)
- baml_language/crates/baml_compiler2_tir/src/builder.rs
Merging this PR will improve performance by 21.03%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | WallTime | e2e_100_functions |
250.8 ms | 210.7 ms | +19.06% |
| ⚡ | WallTime | vm_loop_500k |
37.3 ms | 30 ms | +24.17% |
| ⚡ | WallTime | e2e_fib_20 |
161.7 ms | 134.4 ms | +20.31% |
| ⚡ | WallTime | compile_to_engine |
156.7 ms | 129.6 ms | +20.88% |
| ⚡ | WallTime | vm_field_access_50k |
10.8 ms | 9 ms | +19.76% |
| ⚡ | WallTime | vm_mixed_ops |
21.5 ms | 12.7 ms | +68.93% |
| ⚡ | WallTime | vm_nested_loop |
8.4 ms | 7.2 ms | +16.88% |
| ⚡ | WallTime | e2e_hello_world |
157.7 ms | 130.4 ms | +20.95% |
| ⚡ | WallTime | vm_call_chain_100_x_5k |
53.2 ms | 46.4 ms | +14.67% |
| ⚡ | WallTime | vm_closure_call_50k |
13.8 ms | 12.4 ms | +11.07% |
| ⚡ | WallTime | vm_fib_20 |
8.8 ms | 7.6 ms | +16.5% |
| ⚡ | WallTime | e2e_arithmetic |
157.6 ms | 131 ms | +20.3% |
| ⚡ | WallTime | startup_empty_expression |
157.3 ms | 131.3 ms | +19.81% |
| ⚡ | WallTime | vm_class_create_50k |
18.3 ms | 16.6 ms | +10.33% |
| ⚡ | WallTime | e2e_class_and_loop |
160.9 ms | 133.3 ms | +20.7% |
Tip
Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.
Comparing kai/bigint (14b614b) with canary (7a03331)1
Footnotes
- doc tests - Generate binding
- Add bigint to matches it was missing in - Negative shift now correctly throws a BAML panic - Doc fixes
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
baml_language/crates/sys_llm/src/types/output_format.rs (1)
455-478:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd
Ty::Bigintto multiline rendering checks for consistency.Bigint is missing from two primitive pattern matches used to determine whether list/union rendering needs multiple lines. This causes
List<bigint>to render multiline ([\n bigint\n]) instead of inline (bigint[]), inconsistent with howList<int>and other numeric primitives render.📝 Proposed fix
let needs_multiline = !is_hoisted && match inner.as_ref() { Ty::String { .. } | Ty::Int { .. } + | Ty::Bigint { .. } | Ty::Float { .. } | Ty::Bool { .. } | Ty::Null { .. } => false, Ty::Enum(tn, _) => { // Inline enums render short; hoisted ones are just a name !hoisted_enums.contains(tn.display_name.as_str()) && inner_str.len() > 15 } Ty::Union(items, _) => items.iter().all(|t| { !matches!( t, Ty::String { .. } | Ty::Int { .. } + | Ty::Bigint { .. } | Ty::Float { .. } | Ty::Bool { .. } | Ty::Null { .. } ) }), _ => true, };Consider adding a test
test_render_list_of_bigint(mirroringtest_render_list_of_intat line 968) to verify inline rendering.🤖 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/sys_llm/src/types/output_format.rs` around lines 455 - 478, The multiline-detection match in the needs_multiline calculation omits Ty::Bigint, causing List<bigint> and unions containing bigint to be treated as non-primitive and rendered multiline; update both pattern matches that currently list Ty::String, Ty::Int, Ty::Float, Ty::Bool, Ty::Null to also include Ty::Bigint so that bigint is treated like other primitive numerics (adjust the Ty::Enum / Ty::Union arms as needed), ensuring the computation around needs_multiline, inner_str length checks, and hoisted_enums behavior remains consistent; add a test mirroring test_render_list_of_int named test_render_list_of_bigint to assert inline rendering.
🤖 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.
Outside diff comments:
In `@baml_language/crates/sys_llm/src/types/output_format.rs`:
- Around line 455-478: The multiline-detection match in the needs_multiline
calculation omits Ty::Bigint, causing List<bigint> and unions containing bigint
to be treated as non-primitive and rendered multiline; update both pattern
matches that currently list Ty::String, Ty::Int, Ty::Float, Ty::Bool, Ty::Null
to also include Ty::Bigint so that bigint is treated like other primitive
numerics (adjust the Ty::Enum / Ty::Union arms as needed), ensuring the
computation around needs_multiline, inner_str length checks, and hoisted_enums
behavior remains consistent; add a test mirroring test_render_list_of_int named
test_render_list_of_bigint to assert inline rendering.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 8ebd9ebd-65ed-4cda-9166-262361164475
⛔ Files ignored due to path filters (8)
baml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_package_listing.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____03_hir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_tir.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/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!**/*.snap
📒 Files selected for processing (13)
baml_language/crates/baml_builtins2/baml_std/baml/ns_panics/panics.bamlbaml_language/crates/baml_compiler2_ast/src/lower_expr_body.rsbaml_language/crates/baml_compiler2_mir/src/lower.rsbaml_language/crates/baml_compiler_parser/src/parser.rsbaml_language/crates/baml_tests/tests/bigints.rsbaml_language/crates/baml_tests/tests/exceptions.rsbaml_language/crates/baml_type/src/lib.rsbaml_language/crates/bex_engine/src/conversion.rsbaml_language/crates/bex_vm/src/errors.rsbaml_language/crates/bex_vm/src/vm.rsbaml_language/crates/bex_vm_types/src/bytecode.rsbaml_language/crates/bridge_ctypes/src/value_decode.rsbaml_language/crates/sys_llm/src/types/output_format.rs
✅ Files skipped from review due to trivial changes (1)
- baml_language/crates/baml_builtins2/baml_std/baml/ns_panics/panics.baml
🚧 Files skipped from review as they are similar to previous changes (10)
- baml_language/crates/bex_engine/src/conversion.rs
- baml_language/crates/baml_compiler2_mir/src/lower.rs
- baml_language/crates/baml_compiler2_ast/src/lower_expr_body.rs
- baml_language/crates/baml_tests/tests/exceptions.rs
- baml_language/crates/baml_type/src/lib.rs
- baml_language/crates/bridge_ctypes/src/value_decode.rs
- baml_language/crates/baml_compiler_parser/src/parser.rs
- baml_language/crates/bex_vm/src/vm.rs
- baml_language/crates/bex_vm_types/src/bytecode.rs
- baml_language/crates/baml_tests/tests/bigints.rs
Passing an `int` into a generic function that explicitly has `<bigint>` generic parameters should widen the `int`
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 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_compiler2_tir/src/builder.rs`:
- Around line 7792-7829: The union-reduction in infer_bitwise (inner function
base_ty) rejects mixed int|bigint unions because it only accepts identical
primitives; update base_ty (used by infer_bitwise) to scan union members and
allow widening: if all members reduce to either Int or Bigint and at least one
is Bigint, return PrimitiveType::Bigint; if all are Int return
PrimitiveType::Int; otherwise return None. Ensure literals (Literal::Int /
Literal::Bigint) are treated as Int/Bigint when collecting members so
expressions like int|bigint & 1n correctly reduce to bigint.
- Around line 7605-7619: The code treats comparisons like BinaryOp::Ge as valid
when one side is a union type that may include float and the other is bigint (or
vice versa); extend the float/bigint detection to handle union-shaped types by
either updating is_float_bigint_mix to recurse into Ty::Union (and detect if any
union constituent is float while the other side contains bigint) or add a new
helper (e.g., is_union_float_bigint_mix) invoked where BinaryOp::Ge (and the
other ranges 7766-7786) currently call is_float_bigint_mix; ensure you still
skip Ty::Unknown and Ty::Error branches and call self.context.report_simple with
TirTypeError::InvalidBinaryOp when the union-aware check finds a float↔bigint
possibility.
In `@baml_language/crates/bex_engine/src/conversion.rs`:
- Around line 825-851: coerce_arg_to_declared_type currently only rewrites outer
containers and therefore lets nested Int values in structured types
(list<bigint>, map<string,bigint>, class fields, optional/union children) bypass
the int→bigint widening; update coerce_arg_to_declared_type (and/or
convert_external_to_vm_value) to recurse into declared child types so every
element/entry/field is coerced according to its Ty: when matching
Ty::List(inner), Ty::Map(key, val), Ty::Class(..., fields, ...),
Ty::Optional(inner), Ty::Union(variants), etc., walk the contained values and
call coerce_arg_to_declared_type (or convert_external_to_vm_value where
appropriate) on each child so Int values are widened to BigInt via
coerce_numeric_to_declared_type inside nested structures.
- Around line 898-910: The union-handling branch in the (v, Ty::Union(members,
_)) match only checks for Ty::Int and Ty::Bigint, so numeric literal union
members (e.g., 1 or 1n) are ignored; update the checks and the target-finding
iterator to also recognize the integer and bigint literal type variants (the
literal enum variants used in Ty, e.g., Ty::IntLiteral / Ty::BigintLiteral or
whatever the crate uses) so has_int/has_bigint and the .find(...) consider both
declared and literal numeric members, then pass that found target into
coerce_numeric_to_declared_type as before.
In `@baml_language/crates/bex_vm/src/package_baml/bigint.rs`:
- Around line 162-189: The parse function currently constructs a BigInt from
arbitrary-length decimal text (in parse) without enforcing MAX_BIGINT_BITS; add
a conservative preflight that rejects inputs whose decimal magnitude could
exceed MAX_BIGINT_BITS before calling BigInt::parse_bytes. Specifically: in
parse (the function), after stripping sign (sign_str/digits) trim leading zeros
from digits, count remaining decimal digits, compute an upper-bound on bits
using digits * LOG2_10 (use a constant like LOG2_10 = 3.321928094887362) or
convert MAX_BIGINT_BITS to a maximum allowed decimal digits by
floor(MAX_BIGINT_BITS / LOG2_10) (+1 safety margin), and if the digit count
exceeds that threshold return Err(VmBamlError::AllocFailure { message:
format!("bigint.parse: allocation would exceed MAX_BIGINT_BITS") }.into())
instead of proceeding to BigInt::parse_bytes; only call BigInt::parse_bytes if
the preflight passes.
- Around line 136-159: The ilog binary search currently computes candidate =
base.pow(mid) which can allocate past MAX_BIGINT_BITS; before calling
base.pow(mid) in ilog, estimate the bit-size of b^mid (e.g., bits(candidate) ≤
base.bits().saturating_mul(u64::from(mid))) and if that estimated bits >
MAX_BIGINT_BITS treat the candidate as "too large" (i.e., set hi = mid - 1) so
you never call base.pow for an oversized exponent; use the existing symbols
ilog, base.bits(), MAX_BIGINT_BITS, and bigint.bits() and keep the existing loop
invariant (handle mid == 0 specially so no underflow) so allocations are avoided
and AllocFailure path is preserved.
- Around line 90-106: The current pre-flight uses base_bits * exp which is an
overly loose upper bound and rejects valid exponents (e.g. powers of two);
change the estimate to the provable lower bound bits(base^exp) ≥
exp*(bits(base)-1)+1 so we only fail when the real result must exceed
MAX_BIGINT_BITS. In the bigint.pow pre-flight (where base_bits and exp_u32 are
computed) replace the estimated_bits computation with an integer-safe
lower-bound: compute estimated_bits =
(u64::from(exp_u32)).saturating_mul(base_bits.saturating_sub(1)).saturating_add(1)
and compare that to MAX_BIGINT_BITS; keep the later actual
multiplication/alloc-failure check in place as the final safety net.
- Around line 48-57: The isqrt function uses bigint.sqrt() but the Roots trait
from num_integer is not imported; add an import for the trait (e.g. include use
num_integer::Roots;) in the module where isqrt (function name isqrt and type
BigInt) is defined so BigInt::sqrt() is available, then rebuild to ensure the
compile error is resolved.
🪄 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: 1001a7b3-55f9-4fde-88ff-acfd1d7cd3b0
⛔ Files ignored due to path filters (10)
baml_language/Cargo.lockis excluded by!**/*.lockbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__04_tir.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__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__04_tir.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/bridge_nodejs/proto.d.ts.mapis excluded by!**/*.mapbaml_language/crates/bridge_nodejs/proto.js.mapis excluded by!**/*.mapbaml_language/sdks/python/uv.lockis excluded by!**/*.lock
📒 Files selected for processing (20)
baml_language/crates/baml_compiler2_mir/src/lower.rsbaml_language/crates/baml_compiler2_tir/Cargo.tomlbaml_language/crates/baml_compiler2_tir/src/builder.rsbaml_language/crates/baml_tests/tests/bigints.rsbaml_language/crates/baml_type/src/lib.rsbaml_language/crates/bex_engine/Cargo.tomlbaml_language/crates/bex_engine/src/conversion.rsbaml_language/crates/bex_engine/src/lib.rsbaml_language/crates/bex_project/src/bex.rsbaml_language/crates/bex_vm/src/package_baml/bigint.rsbaml_language/crates/bridge_ctypes/src/value_encode.rsbaml_language/crates/bridge_ctypes/types/baml_core/cffi/v1/baml_outbound.protobaml_language/crates/bridge_nodejs/proto.jsbaml_language/crates/bridge_nodejs/typescript_src/proto.tsbaml_language/crates/bridge_nodejs/typescript_src/proto/baml_cffi.d.tsbaml_language/crates/bridge_nodejs/typescript_src/proto/baml_cffi.jsbaml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pybaml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pyibaml_language/sdks/python/src/baml_core/proto.pybaml_language/sdks/python/tests/test_bigint.py
✅ Files skipped from review due to trivial changes (4)
- baml_language/crates/baml_compiler2_tir/Cargo.toml
- baml_language/crates/bex_engine/Cargo.toml
- baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.py
- baml_language/crates/bridge_nodejs/typescript_src/proto/baml_cffi.js
🚧 Files skipped from review as they are similar to previous changes (3)
- baml_language/crates/bridge_nodejs/typescript_src/proto.ts
- baml_language/crates/baml_type/src/lib.rs
- baml_language/crates/baml_compiler2_mir/src/lower.rs
| | BinaryOp::Ge => { | ||
| if Self::is_float_bigint_mix(lhs, rhs) | ||
| && !matches!(lhs, Ty::Unknown { .. } | Ty::Error { .. }) | ||
| && !matches!(rhs, Ty::Unknown { .. } | Ty::Error { .. }) | ||
| { | ||
| self.context.report_simple( | ||
| TirTypeError::InvalidBinaryOp { | ||
| op, | ||
| lhs: lhs.clone(), | ||
| rhs: rhs.clone(), | ||
| }, | ||
| at, | ||
| ); | ||
| } | ||
| Ty::Primitive(PrimitiveType::Bool, TyAttr::default()) |
There was a problem hiding this comment.
Handle union-shaped float/bigint comparisons.
is_float_bigint_mix only recognizes direct float/bigint primitives and literals, so something like float | int compared against bigint falls through here as a valid bool expression even though one runtime branch is the forbidden float↔bigint case.
Also applies to: 7766-7786
🤖 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_compiler2_tir/src/builder.rs` around lines 7605 -
7619, The code treats comparisons like BinaryOp::Ge as valid when one side is a
union type that may include float and the other is bigint (or vice versa);
extend the float/bigint detection to handle union-shaped types by either
updating is_float_bigint_mix to recurse into Ty::Union (and detect if any union
constituent is float while the other side contains bigint) or add a new helper
(e.g., is_union_float_bigint_mix) invoked where BinaryOp::Ge (and the other
ranges 7766-7786) currently call is_float_bigint_mix; ensure you still skip
Ty::Unknown and Ty::Error branches and call self.context.report_simple with
TirTypeError::InvalidBinaryOp when the union-aware check finds a float↔bigint
possibility.
| fn infer_bitwise(lhs: &Ty, rhs: &Ty) -> Ty { | ||
| fn base_ty(ty: &Ty) -> Option<PrimitiveType> { | ||
| // Bitwise only accepts Int and Bigint. Float / String / Bool | ||
| // return `None` so the outer match falls through to `Unknown` | ||
| // (which surfaces as `InvalidBinaryOp`). | ||
| match ty { | ||
| Ty::Primitive(PrimitiveType::Int, _) => Some(PrimitiveType::Int), | ||
| Ty::Primitive(PrimitiveType::Bigint, _) => Some(PrimitiveType::Bigint), | ||
| Ty::Literal(baml_base::Literal::Int(_), _, _) => Some(PrimitiveType::Int), | ||
| Ty::Literal(baml_base::Literal::Bigint(_), _, _) => Some(PrimitiveType::Bigint), | ||
| Ty::Union(members, _) => { | ||
| let mut result: Option<PrimitiveType> = None; | ||
| for m in members { | ||
| let p = base_ty(m)?; | ||
| result = Some(match (result, p) { | ||
| (None, p) => p, | ||
| (Some(a), b) if a == b => a, | ||
| _ => return None, | ||
| }); | ||
| } | ||
| result | ||
| } | ||
| _ => None, | ||
| } | ||
| } | ||
|
|
||
| match (base_ty(lhs), base_ty(rhs)) { | ||
| (Some(PrimitiveType::Int), Some(PrimitiveType::Int)) => { | ||
| Ty::Primitive(PrimitiveType::Int, TyAttr::default()) | ||
| } | ||
| (Some(PrimitiveType::Bigint | PrimitiveType::Int), Some(PrimitiveType::Bigint)) | ||
| | (Some(PrimitiveType::Bigint), Some(PrimitiveType::Int)) => { | ||
| Ty::Primitive(PrimitiveType::Bigint, TyAttr::default()) | ||
| } | ||
| _ => Ty::Unknown { | ||
| attr: TyAttr::default(), | ||
| }, | ||
| } |
There was a problem hiding this comment.
Keep int→bigint widening when reducing union operands for bitwise ops.
The union reducer in infer_bitwise only succeeds when every union member is the exact same primitive, so int | bigint operands get rejected as Unknown. That makes valid cases like let x: int | bigint; x & 1n fail type-checking even though every branch is legal under the new binary widening rules and should produce bigint.
🤖 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_compiler2_tir/src/builder.rs` around lines 7792 -
7829, The union-reduction in infer_bitwise (inner function base_ty) rejects
mixed int|bigint unions because it only accepts identical primitives; update
base_ty (used by infer_bitwise) to scan union members and allow widening: if all
members reduce to either Int or Bigint and at least one is Bigint, return
PrimitiveType::Bigint; if all are Int return PrimitiveType::Int; otherwise
return None. Ensure literals (Literal::Int / Literal::Bigint) are treated as
Int/Bigint when collecting members so expressions like int|bigint & 1n correctly
reduce to bigint.
| pub(crate) fn coerce_arg_to_declared_type( | ||
| value: BexExternalValue, | ||
| ty: &Ty, | ||
| ) -> Result<BexExternalValue, EngineError> { | ||
| match (value, ty) { | ||
| // ── Class / enum naming (incoming only) ────────────────────────── | ||
| (BexExternalValue::Map { entries, .. }, Ty::Class(type_name, _, _)) => { | ||
| Ok(BexExternalValue::Instance { | ||
| class_name: type_name.to_string(), | ||
| fields: entries, | ||
| }) | ||
| } | ||
| (BexExternalValue::Instance { fields, .. }, Ty::Class(type_name, _, _)) => { | ||
| Ok(BexExternalValue::Instance { | ||
| class_name: type_name.to_string(), | ||
| fields, | ||
| }) | ||
| } | ||
| (BexExternalValue::Variant { variant_name, .. }, Ty::Enum(type_name, _)) => { | ||
| Ok(BexExternalValue::Variant { | ||
| enum_name: type_name.to_string(), | ||
| variant_name, | ||
| }) | ||
| } | ||
|
|
||
| // ── Numeric / optional / union ─────────────────────────────────── | ||
| (v, ty) => coerce_numeric_to_declared_type(v, ty), |
There was a problem hiding this comment.
Structured bigint slots still bypass widening.
This only rewrites the outer value shape. list<bigint>, map<string, bigint>, and bigint-typed class fields can still carry nested Int values into the VM because neither this helper nor convert_external_to_vm_value walks declared child types. That makes the new int→bigint widening rule false for structured inputs and lets those values round-trip back out as int.
🤖 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_engine/src/conversion.rs` around lines 825 - 851,
coerce_arg_to_declared_type currently only rewrites outer containers and
therefore lets nested Int values in structured types (list<bigint>,
map<string,bigint>, class fields, optional/union children) bypass the int→bigint
widening; update coerce_arg_to_declared_type (and/or
convert_external_to_vm_value) to recurse into declared child types so every
element/entry/field is coerced according to its Ty: when matching
Ty::List(inner), Ty::Map(key, val), Ty::Class(..., fields, ...),
Ty::Optional(inner), Ty::Union(variants), etc., walk the contained values and
call coerce_arg_to_declared_type (or convert_external_to_vm_value where
appropriate) on each child so Int values are widened to BigInt via
coerce_numeric_to_declared_type inside nested structures.
There was a problem hiding this comment.
♻️ Duplicate comments (5)
baml_language/crates/bex_vm/src/package_baml/bigint.rs (3)
146-160:⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift
ilog's binary search can materialise candidates larger thanMAX_BIGINT_BITS.
base.pow(mid)is called for every midpoint with no allocation guard. For inputs near the cap, intermediate candidates can be substantially larger thanbigintitself (e.g.,bits(base^mid) ≈ mid · bits(base), which forbase = 3andmid ≈ k_max ≈ bits(bigint)is ~1.58× the input), so this path can bypass the recoverableAllocFailureand OOM the process internally.Either bound the candidate's estimated bits before calling
base.pow(mid)(e.g., ifmid.saturating_mul(base_bits) > MAX_BIGINT_BITStreat it as "too large" and sethi = mid - 1), or compare againstbigint.bits()to short-circuit. Keep the special-casemid == 0to avoid underflow.🤖 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_baml/bigint.rs` around lines 146 - 160, The binary search in ilog calls base.pow(mid) unguarded and can allocate values exceeding MAX_BIGINT_BITS; modify the loop around base.pow(mid) (referencing ilog, k_max, base.pow(mid), and bigint) to first estimate candidate bit-size (e.g., compute base_bits = base.bits() or similar and check mid.saturating_mul(base_bits) > MAX_BIGINT_BITS) or compare mid * base_bits against bigint.bits(), and if that estimate shows the candidate would be too large treat it as "too large" by setting hi = mid - 1 (keeping the special-case for mid == 0 to avoid underflow); only call base.pow(mid) when the estimated bits are within limits so AllocFailure/OOM is avoided.
162-190:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
bigint.parseignoresMAX_BIGINT_BITS.This path allocates arbitrary-length decimal text straight into
BigInt, so a multi-megabyte digit string can produce a bigint that literals and arithmetic operators are supposed to reject withAllocFailure. A conservative preflight on the trimmed digit count (e.g., reject whendigits.len() * log2(10) > MAX_BIGINT_BITS, with a small safety margin) closes the bypass beforeparse_bytes.🤖 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_baml/bigint.rs` around lines 162 - 190, The parse function currently converts arbitrary-length decimal strings into BigInt without checking MAX_BIGINT_BITS; add a preflight size check in the parse(text: &str) function after extracting `digits` that computes an upper-bound bit length (e.g., estimated_bits = digits.len() as f64 * LOG2_10 where LOG2_10 ≈ 3.321928094887362) and rejects input when estimated_bits exceeds MAX_BIGINT_BITS minus a small safety margin, returning the appropriate allocation failure error (use the same error variant your codebase uses for oversized bigints, e.g., VmBamlError::AllocFailure or similar) instead of calling BigInt::parse_bytes for those cases so huge digit strings cannot bypass the allocator limits.
90-108:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
powpre-flight still overestimates by a factor of ~bits(base)/(bits(base)-1).
estimated_bits = base_bits * expis a loose upper bound, not a lower bound on the result size, so valid inputs nearMAX_BIGINT_BITSget rejected withAllocFailure. The exact lower bound is(bits(base) - 1) * exp + 1— using that only rejects when the result truly must exceed the cap.For example, with
MAX_BIGINT_BITS = 1 << 28, a base of 3 (bits = 2) andexp ≈ 168Mproduces a result of ~266M bits (under the cap), but the current check sees2 * 168M = 336M > capand rejects.♻️ Proposed fix
- let estimated_bits = base_bits.saturating_mul(u64::from(exp_u32)); + // bits(b^e) ≥ (bits(b) - 1) * e + 1 for |b| ≥ 2 — the tightest + // lower bound, so we only reject results that *must* exceed the cap. + let estimated_bits = u64::from(exp_u32) + .saturating_mul(base_bits.saturating_sub(1)) + .saturating_add(1); if estimated_bits > MAX_BIGINT_BITS {🤖 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_baml/bigint.rs` around lines 90 - 108, The pre-flight estimate uses estimated_bits = base_bits * exp which overestimates and rejects valid inputs; replace it with the tight lower bound (bits(base) - 1) * exp + 1. Concretely, after computing base_bits and exp_u32, compute estimated_bits = if base_bits == 0 { 0 } else { base_bits.saturating_sub(1).saturating_mul(u64::from(exp_u32)).saturating_add(1) } and then compare that against MAX_BIGINT_BITS; keep the existing alloc_failure_panic paths and final Ok(Arc::new(bigint.pow(exp_u32))). Use the symbols base_bits, exp_u32, estimated_bits, MAX_BIGINT_BITS, bigint.pow and alloc_failure_panic to locate and change the logic.baml_language/crates/bex_engine/src/conversion.rs (2)
887-900:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUnion widening still ignores numeric literal members.
has_int/has_bigintand thefindtarget only considerTy::Int { .. }/Ty::Bigint { .. }, notTy::Literal(Literal::Int(_), _)/Ty::Literal(Literal::Bigint(_), _). For unions like1n | stringor1 | bigint, the widening path is never entered even thoughvalue_matches_type(line 558/559) andfind_matching_union_member(line 619/684) already accept those literal arms, so an incomingIntheaded for a bigint-literal union slot survives as the wrong numeric kind and fails downstream selection.♻️ Proposed fix
(v, Ty::Union(members, _)) => { - let has_int = members.iter().any(|m| matches!(m, Ty::Int { .. })); - let has_bigint = members.iter().any(|m| matches!(m, Ty::Bigint { .. })); + let has_int = members + .iter() + .any(|m| matches!(m, Ty::Int { .. } | Ty::Literal(Literal::Int(_), _))); + let has_bigint = members.iter().any(|m| { + matches!(m, Ty::Bigint { .. } | Ty::Literal(Literal::Bigint(_), _)) + }); if has_int == has_bigint { Ok(v) } else if let Some(target) = members .iter() - .find(|m| matches!(m, Ty::Int { .. } | Ty::Bigint { .. })) + .find(|m| { + matches!( + m, + Ty::Int { .. } + | Ty::Bigint { .. } + | Ty::Literal(Literal::Int(_), _) + | Ty::Literal(Literal::Bigint(_), _) + ) + }) { coerce_numeric_to_declared_type(v, target) } else { Ok(v) } }🤖 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_engine/src/conversion.rs` around lines 887 - 900, The union-widening branch in conversion.rs only checks for Ty::Int and Ty::Bigint and therefore ignores numeric literal members; update the (v, Ty::Union(...)) arm to treat Ty::Literal(Literal::Int(_), _) as an Int member and Ty::Literal(Literal::Bigint(_), _) as a Bigint member when computing has_int/has_bigint and when locating the target in the .find(...) so that coerce_numeric_to_declared_type(v, target) is invoked for unions like `1 | bigint` or `1n | string`; adjust the matches! patterns used in the has_* booleans and the .find closure to include these Ty::Literal cases (leaving the call to coerce_numeric_to_declared_type unchanged).
825-853:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftNested
bigintslots still bypassInt → Bigintwidening.
coerce_arg_to_declared_typeonly rewrites the outermost shape; the Map→Instance and Instance/Variant arms moveentries/fieldsthrough untouched, andconvert_external_to_vm_valuedoesn't consult declared child types either. SoIntvalues nested insidelist<bigint>,map<string, bigint>, or bigint-typed class/optional fields are still allocated as VMIntrather than widened, breaking the documented int→bigint widening rule for structured inputs.Recursing into declared child types (
Ty::List/Ty::Map/Ty::Classfield-by-field/Ty::Optional) before/while callingconvert_external_to_vm_valuewould close this.🤖 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_engine/src/conversion.rs` around lines 825 - 853, coerce_arg_to_declared_type currently only rewrites the top-level shape (Map→Instance, Instance, Variant) and leaves nested values unchanged so Ints inside structured types don't get widened to Bigint; fix by recursing into declared child types before converting: in coerce_arg_to_declared_type, when matching Ty::Class, Ty::List, Ty::Map and Ty::Optional, iterate the corresponding child type(s) and call convert_external_to_vm_value (or the existing conversion path) on each entry/field/element using the declared child Ty so nested Int→Bigint widening occurs; specifically update the Map { entries }→Instance and Instance { fields } arms to map each entry/field through conversion using the class field types from Ty::Class, handle Ty::List/Ty::Map/Ty::Optional by converting their inner values with the inner Ty, and ensure Variant handling similarly consults enum variant payload types if present.
🧹 Nitpick comments (1)
baml_language/crates/bex_vm/src/package_baml/bigint.rs (1)
207-226: ⚡ Quick winSwitch
bigint.randomto bit-granular rejection sampling to improve worst-case acceptance rate.The current byte-granular implementation allocates
range.to_bytes_be().len()bytes for sampling, which wastes entropy whenrangeis just above a byte boundary. For example, withrange = 257, sampling 2 bytes gives an acceptance rate of only 257/65536 ≈ 0.39%, requiring ~256getrandomsyscalls per call on average. Similar pathological cases occur for anyrange = 2^k + 1.Switching to bit-granular sampling—compute
range.bits(), drawceil(bits / 8)bytes, then mask the high byte to the topbits % 8bits—keeps acceptance at ≥ 50% and bounds expected iterations to ≤ 2. This approach aligns with standard implementations likenum-bigint'sgen_biguint_below.🤖 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_baml/bigint.rs` around lines 207 - 226, The current byte-granular rejection sampling in bigint.random wastes entropy for ranges just above byte boundaries; change it to bit-granular sampling by computing let bits = range.bits(), let byte_len = (bits + 7) / 8, draw byte_len bytes, then mask the top byte to keep only bits % 8 high bits (no mask if bits % 8 == 0) before constructing BigUint; keep the same rejection condition (sample < range) and return BigInt::from(sample) + lower.as_ref() wrapped in Arc as before; update the buffer size and masking logic in the function (look for bigint.random / the loop using range.to_bytes_be(), buf, getrandom::getrandom, BigUint::from_bytes_be, and the return constructing BigInt) so acceptance rate is >=50% and iterations are bounded.
🤖 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.
Duplicate comments:
In `@baml_language/crates/bex_engine/src/conversion.rs`:
- Around line 887-900: The union-widening branch in conversion.rs only checks
for Ty::Int and Ty::Bigint and therefore ignores numeric literal members; update
the (v, Ty::Union(...)) arm to treat Ty::Literal(Literal::Int(_), _) as an Int
member and Ty::Literal(Literal::Bigint(_), _) as a Bigint member when computing
has_int/has_bigint and when locating the target in the .find(...) so that
coerce_numeric_to_declared_type(v, target) is invoked for unions like `1 |
bigint` or `1n | string`; adjust the matches! patterns used in the has_*
booleans and the .find closure to include these Ty::Literal cases (leaving the
call to coerce_numeric_to_declared_type unchanged).
- Around line 825-853: coerce_arg_to_declared_type currently only rewrites the
top-level shape (Map→Instance, Instance, Variant) and leaves nested values
unchanged so Ints inside structured types don't get widened to Bigint; fix by
recursing into declared child types before converting: in
coerce_arg_to_declared_type, when matching Ty::Class, Ty::List, Ty::Map and
Ty::Optional, iterate the corresponding child type(s) and call
convert_external_to_vm_value (or the existing conversion path) on each
entry/field/element using the declared child Ty so nested Int→Bigint widening
occurs; specifically update the Map { entries }→Instance and Instance { fields }
arms to map each entry/field through conversion using the class field types from
Ty::Class, handle Ty::List/Ty::Map/Ty::Optional by converting their inner values
with the inner Ty, and ensure Variant handling similarly consults enum variant
payload types if present.
In `@baml_language/crates/bex_vm/src/package_baml/bigint.rs`:
- Around line 146-160: The binary search in ilog calls base.pow(mid) unguarded
and can allocate values exceeding MAX_BIGINT_BITS; modify the loop around
base.pow(mid) (referencing ilog, k_max, base.pow(mid), and bigint) to first
estimate candidate bit-size (e.g., compute base_bits = base.bits() or similar
and check mid.saturating_mul(base_bits) > MAX_BIGINT_BITS) or compare mid *
base_bits against bigint.bits(), and if that estimate shows the candidate would
be too large treat it as "too large" by setting hi = mid - 1 (keeping the
special-case for mid == 0 to avoid underflow); only call base.pow(mid) when the
estimated bits are within limits so AllocFailure/OOM is avoided.
- Around line 162-190: The parse function currently converts arbitrary-length
decimal strings into BigInt without checking MAX_BIGINT_BITS; add a preflight
size check in the parse(text: &str) function after extracting `digits` that
computes an upper-bound bit length (e.g., estimated_bits = digits.len() as f64 *
LOG2_10 where LOG2_10 ≈ 3.321928094887362) and rejects input when estimated_bits
exceeds MAX_BIGINT_BITS minus a small safety margin, returning the appropriate
allocation failure error (use the same error variant your codebase uses for
oversized bigints, e.g., VmBamlError::AllocFailure or similar) instead of
calling BigInt::parse_bytes for those cases so huge digit strings cannot bypass
the allocator limits.
- Around line 90-108: The pre-flight estimate uses estimated_bits = base_bits *
exp which overestimates and rejects valid inputs; replace it with the tight
lower bound (bits(base) - 1) * exp + 1. Concretely, after computing base_bits
and exp_u32, compute estimated_bits = if base_bits == 0 { 0 } else {
base_bits.saturating_sub(1).saturating_mul(u64::from(exp_u32)).saturating_add(1)
} and then compare that against MAX_BIGINT_BITS; keep the existing
alloc_failure_panic paths and final Ok(Arc::new(bigint.pow(exp_u32))). Use the
symbols base_bits, exp_u32, estimated_bits, MAX_BIGINT_BITS, bigint.pow and
alloc_failure_panic to locate and change the logic.
---
Nitpick comments:
In `@baml_language/crates/bex_vm/src/package_baml/bigint.rs`:
- Around line 207-226: The current byte-granular rejection sampling in
bigint.random wastes entropy for ranges just above byte boundaries; change it to
bit-granular sampling by computing let bits = range.bits(), let byte_len = (bits
+ 7) / 8, draw byte_len bytes, then mask the top byte to keep only bits % 8 high
bits (no mask if bits % 8 == 0) before constructing BigUint; keep the same
rejection condition (sample < range) and return BigInt::from(sample) +
lower.as_ref() wrapped in Arc as before; update the buffer size and masking
logic in the function (look for bigint.random / the loop using
range.to_bytes_be(), buf, getrandom::getrandom, BigUint::from_bytes_be, and the
return constructing BigInt) so acceptance rate is >=50% and iterations are
bounded.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: b24a104f-fb91-4826-8a85-4b464a7d0ee7
⛔ Files ignored due to path filters (8)
baml_language/Cargo.lockis excluded by!**/*.lockbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_arith/baml_tests__compiles__bigint_arith__04_tir.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__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/bigint_cmp/baml_tests__compiles__bigint_cmp__06_codegen.snapis excluded by!**/*.snapbaml_language/sdks/python/uv.lockis excluded by!**/*.lock
📒 Files selected for processing (11)
baml_language/crates/baml_compiler2_mir/src/lower.rsbaml_language/crates/baml_compiler2_tir/Cargo.tomlbaml_language/crates/baml_compiler2_tir/src/builder.rsbaml_language/crates/baml_tests/tests/bigints.rsbaml_language/crates/baml_type/src/lib.rsbaml_language/crates/bex_engine/Cargo.tomlbaml_language/crates/bex_engine/src/conversion.rsbaml_language/crates/bex_engine/src/lib.rsbaml_language/crates/bex_project/src/bex.rsbaml_language/crates/bex_vm/src/package_baml/bigint.rsbaml_language/sdks/python/tests/test_bigint.py
✅ Files skipped from review due to trivial changes (2)
- baml_language/crates/bex_engine/Cargo.toml
- baml_language/crates/baml_compiler2_tir/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (7)
- baml_language/crates/bex_engine/src/lib.rs
- baml_language/crates/bex_project/src/bex.rs
- baml_language/sdks/python/tests/test_bigint.py
- baml_language/crates/baml_type/src/lib.rs
- baml_language/crates/baml_compiler2_tir/src/builder.rs
- baml_language/crates/baml_compiler2_mir/src/lower.rs
- baml_language/crates/baml_tests/tests/bigints.rs
While we had just a bigint, this adds the literal version, similar to `BamlLiteralInt` and others.
While somewhat unlikely, we should not attempt to allocate a Very Large bigint literal.
Adds the
bigintprimitive type, which represents an arbitrary-precision signed integer with sign-extended two's complement bitwise semantics. Likestring, it is an immutable heap-allocated object.bigintliterals: like other popular languages with built-in arbitrary-size integers, we use thensuffix as in123nor9999999999999999999999999nintcan always be safely widened intobigint, so we allow implicit casting for this case. This includes in binary ops, so1n + 2 == 3nbigints (such as left shift) may throw anAllocFailurepanic if the size of thebigintwould exceed1 << 28bits (about 33.6MB). For example:1n << (1n << 29n)will panic. This allows programs to recover in BAML instead of crashing from an out-of-memory error or other allocation problems.bigintliterals like123Nor1.23nSummary by CodeRabbit
New Features
Runtime / VM
FFI / SDK / Protobuf
Tests
Chores