Lower Typed Jerboa import-resolved modules to Rust

ober

cbaa5ec8b2655b9fb8ea8e190177d72085ce9627

diff --git a/docs/typed-jerboa.md b/docs/typed-jerboa.md
index 69e1e1f..18c21e0 100644
--- a/docs/typed-jerboa.md
+++ b/docs/typed-jerboa.md
@@ -286,13 +286,16 @@ Highest-value next steps:
    IR through `*rust-ir-env*` in `typed-module->rust-string` and
    `typed-modules->rust-crate-string`. The wrapper generator still walks
    surface AST, which is fine for ABI-level shape information.
-2. Resolve imports between typed modules. The parser now accepts an optional
-   `(import (module name) ...)` clause and the checker offers
+2. Resolve imports between typed modules. The parser accepts an optional
+   `(import (module name) ...)` clause. The checker offers
    `check-typed-modules` / `check-and-elaborate-typed-modules`, which walk a
    topologically ordered module list and extend each module's type/call/variant
    envs with the previously listed modules' exported declarations. The Rust
-   emitter does not yet emit cross-module `use` declarations or split the
-   generated crate into per-module files.
+   emitter (`typed-modules->rust-crate-string` /
+   `typed-library-forms->rust-crate-string`) now uses the same multi-module
+   elaboration, so cross-module record/variant/def references compile into a
+   single Rust crate. The emitter still inlines all modules into one file and
+   does not yet emit cross-module `use` declarations.
 3. Improve boundary semantics for Option/Result. They currently cross the FFI
    boundary as opaque handles; direct conversion to idiomatic Scheme result
    values is still open.
diff --git a/lib/jerboa/typed/rust.ss b/lib/jerboa/typed/rust.ss
index 0f9bc43..4bfa837 100644
--- a/lib/jerboa/typed/rust.ss
+++ b/lib/jerboa/typed/rust.ss
@@ -1292,11 +1292,22 @@
     (typed-module->rust-string (parse-typed-library form)))
 
   (def (typed-modules->rust-crate-string modules)
-    (let ([ir-envs
-           (map (lambda (m)
-                  (elaborate-module-or-error
-                    m 'typed-modules->rust-crate-string))
-                modules)])
+    ;; Run import-aware elaboration so cross-module references type check.
+    (let* ([results (check-and-elaborate-typed-modules modules)]
+           [ir-envs
+            (map (lambda (entry)
+                   (let ([modname (car entry)]
+                         [errors (cadr entry)]
+                         [defs (caddr entry)])
+                     (unless (null? errors)
+                       (error 'typed-modules->rust-crate-string
+                         "typed module has check errors"
+                         (cons modname (map typed-check-error-kind errors))))
+                     (map (lambda (ed)
+                            (cons (elaborated-def-name ed)
+                                  (elaborated-def-body-ir ed)))
+                          defs)))
+                 results)])
       (with-rust-env modules
         (lambda ()
           (emit-to-string
diff --git a/tests/test-typed-rust.ss b/tests/test-typed-rust.ss
index 11e9ade..d1a11f5 100644
--- a/tests/test-typed-rust.ss
+++ b/tests/test-typed-rust.ss
@@ -336,6 +336,35 @@
        (substring? equality-rust "jt_return_bytes(token_debug(token).into_bytes(), out_ptr, out_len)"))
   #t)
 
+(define import-provider-form
+  '(typed-library (rust import provider)
+     (export inc make-Pt Pt-x Pt-y)
+     (record Pt ((x : Nat) (y : Nat)))
+     (def (inc (x : Nat)) : Nat (+ x 1))))
+
+(define import-consumer-form
+  '(typed-library (rust import consumer)
+     (export bump-pair-x)
+     (import (rust import provider))
+     (def (bump-pair-x (p : Pt)) : Pt
+       (make-Pt (inc (Pt-x p)) (Pt-y p)))))
+
+(define import-crate-rust
+  (typed-library-forms->rust-crate-string
+    (list import-provider-form import-consumer-form)))
+
+(test "rust crate emits provider def"
+  (substring? import-crate-rust "pub fn inc(x: u64) -> u64")
+  #t)
+
+(test "rust crate emits consumer def calling provider"
+  (and (substring? import-crate-rust "pub fn bump_pair_x(p: Pt) -> Pt")
+       (substring? import-crate-rust "inc(")
+       (substring? import-crate-rust "Pt { x:")
+       (substring? import-crate-rust "(p).x")
+       (substring? import-crate-rust "(p).y"))
+  #t)
+
 (printf "~%Typed Rust emitter: ~a passed, ~a failed~%" pass fail)
 (when (> fail 0)
   (exit 1))