Skip to content

Fix string method dispatch misrouting to effects by value content#33

Merged
jaimeam merged 1 commit into
mainfrom
fix/string-method-effect-misdispatch
Jun 4, 2026
Merged

Fix string method dispatch misrouting to effects by value content#33
jaimeam merged 1 commit into
mainfrom
fix/string-method-effect-misdispatch

Conversation

@jaimeam

@jaimeam jaimeam commented Jun 4, 2026

Copy link
Copy Markdown
Owner

Problem

Calling a method on a string literal whose content began with an effect/capability name (Net, Fs, Console, Clock, Rand, Env, Map, Set) misrouted the call to that effect, throwing at runtime (E4004/E4006) — even though astra check reported no errors.

"Netback".to_lower()   // [E4004] capability not available: Net
"Console".to_lower()   // [E4006] unknown method: Console.to_lower
"Coke".to_lower()      // OK

Root cause

Effect namespaces and ordinary strings shared the Value::Text representation. call_method decided "is this an effect?" by inspecting the string's content (name.starts_with("Net")), so any Text value spelling an effect name got hijacked.

Fix

New Value::Effect(String) variant so method dispatch keys off the receiver's type, never its string value. Effect identifiers evaluate to Value::Effect; call_method reaches an effect handler only for Value::Effect receivers (exact-name match). Every other receiver — including all Value::Text — resolves by type via call_value_method.

Tests

  • 3 regression tests: every string method, every effect name as a prefix, exact-match strings, previously-passing cases, and confirmation real effect identifiers still dispatch.
  • Full suite: 396 passed, 0 failed.

Also

  • Documents decision in ADR-008.
  • Fixes 6 pre-existing clippy lints (sort_by_key, collapsible match guards in lsp/typechecker) so pre-commit passes without --no-verify.

🤖 Generated with Claude Code

Method calls on a string literal whose content began with an
effect/capability name (Net, Fs, Console, Clock, Rand, Env, Map, Set)
were misrouted to that effect, throwing at runtime (E4004/E4006) even
though `astra check` reported no errors. Root cause: effect namespaces
and ordinary strings shared the `Value::Text` representation, and
`call_method` decided "is this an effect?" by inspecting the string's
content (`name.starts_with("Net")`), so e.g. `"Netback".to_lower()`
dispatched to the Net effect.

Give effect namespaces a distinct `Value::Effect(String)` variant so
method dispatch keys off the receiver's type, never its string value.
Effect identifiers evaluate to `Value::Effect`; `call_method` reaches an
effect handler only for `Value::Effect` receivers, matching the exact
name. Every other receiver (including all `Value::Text`) resolves by
type via `call_value_method`.

Adds regression tests covering every string method, every effect name as
a string prefix, exact-match strings, the previously-passing cases, and
confirmation that real effect identifiers still dispatch. Documents the
decision in ADR-008.

Also fixes 6 pre-existing clippy lints (sort_by_key, collapsible match
guards in lsp/typechecker) so the pre-commit hook passes without bypass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jaimeam jaimeam merged commit 2b94f11 into main Jun 4, 2026
6 checks passed
@jaimeam jaimeam deleted the fix/string-method-effect-misdispatch branch June 4, 2026 08:37
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