diff --git a/CHANGELOG.md b/CHANGELOG.md index 8429057..4510fdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `httpGet`/`httpPost`, grid `groupBy` aggregation specs, and the `zip*` option dicts now declare their required and optional keys. A required value satisfies an optional parameter, but an optional value does not satisfy a required one. +- The type checker now tracks the value of a string literal (as a `str` + refinement) so a `get` with a known key resolves a shape field the same way + the `:name` getter does: `resp "body" get` yields the declared `body` field's + type instead of the union of every field type, so `httpGet? "body" get?` + type-checks as `bytes`. Because the key rides the stack as a type, it resolves + even when the literal reaches `get` through a variable; a key computed at + runtime still returns the generic `Maybe[value]`. - The language server now reports an informational diagnostic when a `?` unwrap is statically guaranteed to fail — unwrapping a getter (`:k?`) for a field a concrete shape does not declare, or unwrapping a bare `none`. The hint is diff --git a/doc/mshell.md b/doc/mshell.md index ee26cde..e2592b6 100644 --- a/doc/mshell.md +++ b/doc/mshell.md @@ -594,7 +594,12 @@ always present with a possibly-`none` value. A required value satisfies an optional parameter, but an optional value does not satisfy a required one. Reading is unchanged (`:field` is `Maybe[T]`, `:field?` unwraps it); the language server flags `:field?` on a field a concrete shape does not declare, since that -unwrap always fails. +unwrap always fails. A string literal carries its value as a `str` refinement, +so a `get` with a known key resolves the same way as the getter: `resp "body" +get` reads the declared `body` field's type, not the union of every field type, +so it is interchangeable with `resp :body`. The key resolves even when it +reaches `get` through a variable (`"body" k! resp @k get`); a key computed at +runtime returns the generic `Maybe[value]`. ```mshell type Request = {url: str, timeout?: int} diff --git a/doc/type_system.inc.html b/doc/type_system.inc.html index 6aa2649..bae627c 100644 --- a/doc/type_system.inc.html +++ b/doc/type_system.inc.html @@ -244,6 +244,8 @@
Maybe[T] and :field? unwraps it (failing at runtime on a missing key), for required and optional fields alike.
Because of that, the language server emits an informational diagnostic when :field? is used on a field a concrete shape does not declare — that unwrap is guaranteed to fail.
Homogeneous dictionaries ({str: T}) return a genuine Maybe[T] for any key and are never flagged.
+A string literal carries its value as a str refinement, so a get with a known key resolves the same way as the getter — resp "body" get reads the declared body field's type rather than the union of every field type, so it is interchangeable with resp :body.
+The key resolves even when it reaches get through a variable ("body" k! resp @k get); a key computed at runtime returns the generic Maybe[value].