@@ -2332,6 +2332,71 @@ let async_fence_tests = [
23322332 Alcotest. test_case " wasm: async row without async call compiles" `Quick test_async_no_boundary_still_compiles;
23332333]
23342334
2335+ (* ============================================================================
2336+ Issue #555: interpreter resume soundness (multi-shot loud-fail)
2337+ ============================================================================
2338+
2339+ The tree-walking interpreter models `resume` with an identity continuation,
2340+ correct only for single-shot tail-resume. Multi-shot resume (>1 call)
2341+ previously produced a silently-wrong value (each call merely returned its
2342+ argument); it must now fail loudly. Non-tail single-shot resume stays a
2343+ documented shallow-resume incompleteness (undetectable without a CPS
2344+ transform), pinned here as an executable fact. Unlike the existing
2345+ handler-fence tests, these actually APPLY `main` so the handler runs. *)
2346+
2347+ let interp_main path =
2348+ let open Result in
2349+ let ( let * ) = bind in
2350+ let * (prog, _resolve_ctx) = run_frontend path in
2351+ let * env =
2352+ match Interp. eval_program prog with
2353+ | Ok env -> Ok env
2354+ | Error e -> Error (Value. show_eval_error e)
2355+ in
2356+ let * main_fn =
2357+ match Value. lookup_env " main" env with
2358+ | Ok f -> Ok f
2359+ | Error _ -> Error " no `main` binding"
2360+ in
2361+ match Interp. apply_function main_fn [] with
2362+ | Ok v -> Ok v
2363+ | Error e -> Error (Value. show_eval_error e)
2364+
2365+ let test_resume_single_shot_tail () =
2366+ match interp_main (fixture " handle_resume_tail.affine" ) with
2367+ | Ok (Value. VInt 5 ) -> ()
2368+ | Ok v -> Alcotest. failf " single-shot tail-resume: expected VInt 5, got %s" (Value. show_value v)
2369+ | Error msg -> Alcotest. failf " single-shot tail-resume should evaluate, got error: %s" msg
2370+
2371+ let test_resume_multishot_loud_fail () =
2372+ match interp_main (fixture " handle_resume_multishot.affine" ) with
2373+ | Ok v ->
2374+ Alcotest. failf
2375+ " expected a loud multi-shot resume error (Refs #555); got Ok %s — \
2376+ silent multi-shot miscompute has regressed" (Value. show_value v)
2377+ | Error msg ->
2378+ Alcotest. (check bool ) " error names the multi-shot resume limit" true
2379+ (contains_str " multi-shot resume" msg)
2380+
2381+ let test_resume_nontail_known_shallow () =
2382+ (* KNOWN shallow-resume incompleteness: the correct result is 105; the
2383+ shallow interpreter returns the resumed value 5. Flip to VInt 105 when
2384+ delimited continuations land (Refs #555). *)
2385+ match interp_main (fixture " handle_resume_nontail.affine" ) with
2386+ | Ok (Value. VInt 5 ) -> ()
2387+ | Ok (Value. VInt 105 ) ->
2388+ Alcotest. fail
2389+ " non-tail resume now returns 105 — delimited continuations appear to \
2390+ have landed; update this pin and the #555 CAPABILITY-MATRIX note"
2391+ | Ok v -> Alcotest. failf " non-tail resume: expected VInt 5 (known shallow), got %s" (Value. show_value v)
2392+ | Error msg -> Alcotest. failf " non-tail resume should evaluate (shallow), got error: %s" msg
2393+
2394+ let resume_soundness_tests = [
2395+ Alcotest. test_case " interp: single-shot tail-resume evaluates to 5" `Quick test_resume_single_shot_tail;
2396+ Alcotest. test_case " interp: multi-shot resume → loud failure" `Quick test_resume_multishot_loud_fail;
2397+ Alcotest. test_case " interp: non-tail resume → 5 (KNOWN shallow #555)" `Quick test_resume_nontail_known_shallow;
2398+ ]
2399+
23352400(* ============================================================================
23362401 Section: Stage 7 — typed-wasm Ownership Verifier (Tw_verify)
23372402 ============================================================================
@@ -5479,6 +5544,7 @@ let tests =
54795544 (" E2E Try/Catch/Finally" , try_catch_tests);
54805545 (" E2E Handler Fence (#555)" , handler_fence_tests);
54815546 (" E2E Async Fence (#556)" , async_fence_tests);
5547+ (" E2E Resume Soundness (#555)" , resume_soundness_tests);
54825548 (" E2E Ownership Verify" , tw_verify_tests);
54835549 (" E2E Cmd Linearity" , cmd_linear_tests);
54845550 (" E2E Boundary Verify" , tw_interface_tests);
0 commit comments