Skip to content

[codex] Fix string splitting and map key diagnostics - #3861

Merged
aaronvg merged 13 commits into
canaryfrom
codex/b-252-b-533
Jun 27, 2026
Merged

aaronvg merged 13 commits into
canaryfrom
codex/b-252-b-533

Conversation

@aaronvg

@aaronvg aaronvg commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

What changed

  • Fix String.split("") to return codepoint strings without leading/trailing empty entries, including "".split("") == [].
  • Add String.chars() -> string[] for explicit character access.
  • Add Iterable for string, so for ... in over a string iterates codepoint strings via .chars().iter().
  • Reject concrete non-string map<K, V> key annotations during type checking with a clear E0067 diagnostic instead of compiling to a VM .set()/.get() crash.
  • Allow map key aliases that resolve to supported string-key shapes, while still rejecting aliases to non-string keys.
  • Tighten stdlib map equality to map<string, V> and refresh affected LSP/stdlib/bytecode snapshots.
  • Update the SDK type_shapes map fixture to use string-keyed maps.
  • Merge latest origin/canary into the PR branch and refresh bytecode snapshots from the merged tree.

Why

B-252: split("") was exposing Rust/Python-style empty-boundary padding even though users need character-like substrings and string iteration.

B-533: runtime maps are string-keyed today, but the compiler accepted map<int, V>, creating a compile-clean/fail-at-runtime trap. The validation now preserves valid aliases such as type Key = string instead of treating aliases as invalid by default.

Validation

  • cargo fmt
  • cargo nextest run -p baml_tests --test string_regressions --test type_error_repro
  • cargo nextest run -p baml_tests -p baml_lsp2_actions -p baml_lsp2_actions_tests --no-fail-fast
  • cargo nextest run -p baml_tests diagnostic_errors::attr_disambiguation::test_05_diagnostics bytecode_display_formats
  • After merging origin/canary: INSTA_UPDATE=always cargo nextest run -p baml_tests bytecode_display_formats
  • After merging origin/canary: cargo nextest run -p baml_tests --test string_regressions --test type_error_repro
  • For .chars(): INSTA_UPDATE=always cargo nextest run -p baml_tests compiles::__baml_std__::test_03_hir compiles::__baml_std__::test_04_tir compiles::__baml_std__::test_04_5_mir compiles::__baml_std__::test_06_codegen bytecode_display_formats
  • For .chars(): cargo nextest run -p baml_cli describe_command_tests::render_builtin_package_listing
  • For alias map keys: cargo nextest run -p baml_tests --test type_error_repro --test string_regressions
  • For alias map keys: cargo nextest run -p baml_lsp2_actions_tests test_maps_key_and_value_typecheck
  • After pushing latest branch: SKIP=no-commit-to-branch prek run --all-files --show-diff-on-failure --hook-stage manual

Summary by CodeRabbit

  • New Features
    • Added String.chars() for Unicode-aware per-character iteration (string[]).
    • Strings are now iterable over their characters.
  • Bug Fixes
    • Fixed split("") to return correct per-character results for empty and multibyte strings.
  • Improved Diagnostics
    • Added/clarified error E0067 for map keys that aren’t string, including guidance to convert keys via .to_string() before .set()/.get().
  • Tests
    • Updated diagnostics and regression coverage for string iteration and map-key validation.

Note

Medium Risk
Non-string map<K, V> annotations that previously typechecked will now fail at compile time (intentional breaking change). Map-key validation and alias resolution are new type-check paths worth regression-testing.

Overview
Adds String.chars() and makes string implement Iterable (via chars().iter()), so for ... in over strings yields Unicode codepoint strings. Stdlib Equals for maps is narrowed to map<string, V> to match the runtime.

The compiler now rejects map annotations whose key type does not resolve to a string-key shape (with alias expansion), emitting E0067 (InvalidMapKeyType) and LSP wiring instead of compiling maps that fail at .set()/.get(). Test and bytecode/HIR/MIR snapshots are updated for the new builtins and diagnostics.

Reviewed by Cursor Bugbot for commit f23c0a0. Bugbot is set up for automated code reviews on this repo. Configure here.

@linear

linear Bot commented Jun 26, 2026

Copy link
Copy Markdown

B-252

B-533

@vercel

vercel Bot commented Jun 26, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jun 27, 2026 5:05am
promptfiddle Ready Ready Preview, Comment Jun 27, 2026 5:05am
promptfiddle2 Ready Ready Preview, Comment Jun 27, 2026 5:05am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Unicode-aware string character iteration and enforces string-only map keys through lowering, diagnostics, tests, and updated fixtures.

Changes

String iteration

Layer / File(s) Summary
Iterable and chars
baml_language/crates/baml_builtins2/baml_std/baml/string.baml, baml_language/crates/baml_builtins2/baml_std/baml/ns_iter/iter.baml
String.chars() is added, and string implements Iterable by delegating iteration to the character-slice array.
Runtime and regressions
baml_language/crates/bex_vm/src/package_baml/string.rs, baml_language/crates/baml_tests/tests/string_regressions.rs
Empty-delimiter split and .chars() both use per-character substrings, and regression tests cover UTF-8 splitting, iteration, and .chars() indexing.

Map key validation

Layer / File(s) Summary
Key contract and lowering
baml_language/crates/baml_builtins2/baml_std/baml/ns_ops/comparison.baml, baml_language/crates/baml_compiler2_tir/src/infer_context.rs, baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
Equals for maps is narrowed to map<string, V>, InvalidMapKeyType is added, and map lowering rejects unsupported key types.
Diagnostic mapping and repro
baml_language/crates/baml_lsp2_actions/src/check.rs, baml_language/crates/baml_tests/tests/type_error_repro.rs
InvalidMapKeyType maps to DiagnosticId::InvalidMapKeyType, and compile-time regressions cover non-string map keys and string aliases.
Syntax fixtures
baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/class/*, baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/maps/key_and_value_typecheck.baml, baml_language/sdk_tests/fixtures/type_shapes/baml_src/ns_maps/types.baml
Syntax fixtures now render E0067 for non-string map keys, update unresolved-type spans, and change the SDK map type shape to map<string, Resume>.

Sequence Diagram(s)

sequenceDiagram
  participant TypeExprMap as "TypeExpr::Map lowering"
  participant TirTypeError as "TirTypeError::InvalidMapKeyType"
  participant Check as "tir_type_error_to_diagnostic_id"
  participant DiagnosticId as "DiagnosticId::InvalidMapKeyType"

  TypeExprMap->>TirTypeError: emit error for unsupported key type
  TirTypeError->>Check: propagate InvalidMapKeyType
  Check->>DiagnosticId: map to diagnostic id
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A bunny found chars in a UTF-8 stew,
hop-hop, each slice came shining through.
Maps got strict: keys must be string,
or .to_string() will do the thing.
E0067 twinkles, crisp and new 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the two main change areas: string splitting behavior and map key diagnostics.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/b-252-b-533

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 21:26 Inactive
@aaronvg
aaronvg marked this pull request as ready for review June 26, 2026 21:27
@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 21:30 Inactive
@aaronvg
aaronvg marked this pull request as draft June 26, 2026 21:30
@aaronvg
aaronvg marked this pull request as ready for review June 26, 2026 21:31
@github-actions

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 21:34 Inactive
@github-actions

github-actions Bot commented Jun 26, 2026 •

Copy link
Copy Markdown

Binary size checks passed

✅ 7 passed

Artifact Platform File Gzip Gated on Baseline Delta Status
✅ baml-cli Linux 🔒 21.5 MB 9.2 MB file 21.5 MB +19.0 KB (+0.1%) OK
✅ packed-program Linux 🔒 15.6 MB 6.6 MB file 15.6 MB +6.3 KB (+0.0%) OK
✅ baml-cli macOS 🔒 16.5 MB 8.0 MB file 16.1 MB +447.2 KB (+2.8%) OK
✅ packed-program macOS 🔒 12.1 MB 5.7 MB file 12.0 MB +132.8 KB (+1.1%) OK
✅ baml-cli Windows 🔒 18.1 MB 8.2 MB file 18.1 MB +2.6 KB (+0.0%) OK
✅ packed-program Windows 🔒 13.0 MB 5.8 MB file 13.0 MB +5.2 KB (+0.0%) OK
✅ bridge_wasm WASM 14.3 MB 🔒 4.1 MB gzip 4.1 MB +1.9 KB (+0.0%) OK

🔒 = the size this artifact is GATED on (ceiling + delta). Binaries gate on file size (installed binary); WASM gates on gzip (download size). The other size is shown for information only.


Generated by cargo size-gate · workflow run

@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 21:41 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/infer_context.rs`:
- Around line 484-490: The InvalidMapKeyType message in
infer_context::TirTypeError handling is too narrow because it also applies to
invalid map<K, V> annotations, not just .set()/.get() usage. Update the
user-facing text to lead with declaring the map as map<string, V> when the key
type is wrong, and keep the .to_string() conversion hint as secondary guidance;
use the TirTypeError::InvalidMapKeyType branch and key.render_user_facing() as
the place to adjust the wording.
🪄 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: fb07f59f-98d1-4de1-be89-d673f40dec2f

📥 Commits

Reviewing files that changed from the base of the PR and between 62cc633 and 1dcdd1c.

⛔ Files ignored due to path filters (7)
  • baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____03_hir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_5_mir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/attr_disambiguation/baml_tests__diagnostic_errors__attr_disambiguation__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded_unoptimized.snap is excluded by !**/*.snap
📒 Files selected for processing (14)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_iter/iter.baml
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_ops/comparison.baml
  • baml_language/crates/baml_compiler2_tir/src/infer_context.rs
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/class/map_enums_and_literals.baml
  • baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/class/map_types.baml
  • baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/class/map_types2.baml
  • baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/class/secure_types.baml
  • baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/maps/key_and_value_typecheck.baml
  • baml_language/crates/baml_tests/tests/string_regressions.rs
  • baml_language/crates/baml_tests/tests/type_error_repro.rs
  • baml_language/crates/bex_vm/src/package_baml/string.rs
  • baml_language/sdk_tests/fixtures/type_shapes/baml_src/ns_maps/types.baml

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 26, 2026 21:47 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 26, 2026 21:59 Inactive
@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 22:01 Inactive

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 30c7ede. Configure here.

@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 22:05 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/lower_type_expr.rs`:
- Around line 70-101: Treat seen_aliases as a recursion stack in
is_supported_map_key_type_expr: when expanding a TypeExpr::Path alias, keep the
alias inserted only for the duration of the recursive check and remove it before
returning. Update the alias-handling branch in lower_type_expr.rs so a
successful alias expansion does not leave the qtn permanently in seen_aliases,
while still preventing true cycles during recursive descent.
🪄 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: c55029d8-0bf9-4c35-ab86-b9b33c6e0eea

📥 Commits

Reviewing files that changed from the base of the PR and between 6b3cb15 and 30c7ede.

📒 Files selected for processing (2)
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_tests/tests/type_error_repro.rs

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 26, 2026 22:08 Inactive
@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 22:08 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 26, 2026 22:14 Inactive
@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 22:21 Inactive
@aaronvg
aaronvg enabled auto-merge June 26, 2026 22:22
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 26, 2026 22:27 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 26, 2026 22:39 Inactive
@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 22:59 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 26, 2026 23:04 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 26, 2026 23:16 Inactive
@vercel
vercel Bot temporarily deployed to Preview – beps June 26, 2026 23:38 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 26, 2026 23:43 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 26, 2026 23:55 Inactive
# Conflicts:
#	baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/class/map_types2.baml
#	baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/class/secure_types.baml
#	baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded.snap
#	baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded_unoptimized.snap
@vercel
vercel Bot temporarily deployed to Preview – beps June 27, 2026 03:54 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 27, 2026 04:00 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 27, 2026 04:11 Inactive
# Conflicts:
#	baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded.snap
#	baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded_unoptimized.snap
@vercel
vercel Bot temporarily deployed to Preview – beps June 27, 2026 04:48 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 27, 2026 04:54 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 27, 2026 05:06 Inactive
@aaronvg
aaronvg added this pull request to the merge queue Jun 27, 2026
Merged via the queue into canary with commit d5f68a6 Jun 27, 2026
54 checks passed
@aaronvg
aaronvg deleted the codex/b-252-b-533 branch June 27, 2026 05:24

This branch was previously deployed

3 inactive deployments
Preview – promptfiddle — f23c0a0d Deployed Jun 27, 2026 by vercel[bot]
Preview – promptfiddle2 — f23c0a0d Deployed Jun 27, 2026 by vercel[bot]
Preview – beps — f23c0a0d Deployed Jun 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant