Emit inline source comments inside Typed Jerboa Rust bodies

ober

f1f3ad6a2fa87b8c9c2e29b1829045de5ddcf4f6

diff --git a/docs/jerboa-to-rust.md b/docs/jerboa-to-rust.md
index 5ebadd6..931e99a 100644
--- a/docs/jerboa-to-rust.md
+++ b/docs/jerboa-to-rust.md
@@ -108,7 +108,10 @@ Done in subsequent phases:
   ordinary `T` parameter positions (conservative).
 - Generated Rust source comments tied to typed source spans. Records, variants,
   resources, and defs emit `// source: path:line:column` comments above each
-  declaration when the parsed datum carries a source-location.
+  declaration when the parsed datum carries a source-location. Inside function
+  bodies, every `let`, `if`, and `match` IR node also emits an inline
+  `/* source: path:line:column */` block comment so the compiler-reported Rust
+  line can be mapped back to typed source.
 
 Still open:
 
@@ -116,8 +119,6 @@ Still open:
   inlines all modules into a single `lib.rs`.
 - Direct `rustc` / static binary integration polish and eventual LLVM parity
   tests. Today the build goes through `cargo build` only.
-- Expression-level source comments inside function bodies (only the
-  declaration headers carry source spans today).
 - Cross-module `use` declarations and per-module Rust files for richer
   workspaces.
 
@@ -548,12 +549,13 @@ pub fn rope_insert(...) -> Rope { ... }
 ```
 
 Current landing: records, variants, resources, and defs each emit a
-`// source: path:line:column` comment above their generated declaration. The
-checker already threads spans through `typed-check-error-source`, so future
-work can wire expression-level spans into intra-body comments as well as
-richer source maps. When Rust compilation fails, a developer can map the
-reported file to the typed source through these comments. Mapping cargo
-errors directly back to typed source line and column remains future work.
+`// source: path:line:column` comment above their generated declaration, and
+inside function bodies every `let`, `if`, and `match` IR node emits an inline
+`/* source: path:line:column */` block comment so the compiler-reported Rust
+line maps back to typed source. The checker already threads spans through
+`typed-check-error-source` so future work can wire even finer expression-level
+maps (call sites, let-binding right-hand sides) and richer cargo-error
+remapping.
 
 ## Build Integration
 
diff --git a/lib/jerboa/typed/rust.ss b/lib/jerboa/typed/rust.ss
index cf09e91..ff95d57 100644
--- a/lib/jerboa/typed/rust.ss
+++ b/lib/jerboa/typed/rust.ss
@@ -86,6 +86,19 @@
       (when text
         (write-line port level text))))
 
+  (def (rust-inline-source-comment source)
+    (cond
+      [(source-location? source)
+       (string-append
+         "/* source: "
+         (or (source-location-path source) "<unknown>")
+         ":"
+         (number->string (source-location-line source))
+         ":"
+         (number->string (source-location-column source))
+         " */ ")]
+      [else ""]))
+
   (def rust-keywords
     '("as" "break" "const" "continue" "crate" "else" "enum" "extern"
       "false" "fn" "for" "if" "impl" "in" "let" "loop" "match" "mod"
@@ -1369,6 +1382,7 @@
   (def (emit-ir-let ir)
     (string-append
       "{ "
+      (rust-inline-source-comment (typed-ir-node-source ir))
       (join-strings
         (append
           (map (lambda (binding)
@@ -1385,6 +1399,7 @@
 
   (def (emit-ir-if ir)
     (string-append
+      (rust-inline-source-comment (typed-ir-node-source ir))
       "if "
       (emit-expression (typed-ir-if-test ir))
       " { "
@@ -1419,6 +1434,7 @@
             (and default
                  (string-append "_ => " (emit-begin default) ","))])
       (string-append
+        (rust-inline-source-comment (typed-ir-node-source ir))
         "match "
         (emit-expression target)
         " { "
diff --git a/tests/test-typed-rust.ss b/tests/test-typed-rust.ss
index e00fe8f..eb69a2c 100644
--- a/tests/test-typed-rust.ss
+++ b/tests/test-typed-rust.ss
@@ -575,6 +575,21 @@
   (not (substring? calc-rust "// source:"))
   #t)
 
+(define annotated-control-form
+  (car (jerboa-read-file "tests/fixtures/typed/valid-split-tree.ss")))
+
+(define annotated-control-rust
+  (typed-library-form->rust-string annotated-control-form))
+
+(test "rust emits inline source comments above match/if/let in bodies"
+  (and
+    (substring? annotated-control-rust
+      "/* source: tests/fixtures/typed/valid-split-tree.ss:")
+    (or (substring? annotated-control-rust "*/ match ")
+        (substring? annotated-control-rust "*/ if ")
+        (substring? annotated-control-rust "*/ {")))
+  #t)
+
 (printf "~%Typed Rust emitter: ~a passed, ~a failed~%" pass fail)
 (when (> fail 0)
   (exit 1))