Skip to content

Commit f2811ac

Browse files
committed
Fix externref trait-object cast path for wasm-gc
Fixes moonbitlang/moonbit-docs#1123. The wasm-gc backend was emitting invalid cast sequences when trait-object conversion involved #external values across supertrait chains. This change adds a Pidentity lowering path in clam_of_core and tightens Pcast lowering to avoid redundant casts and preserve source/target type intent. In wasm_of_clam_gc, Lcast now handles Ref_extern<->Ref_any with the dedicated conversion ops (Extern_convert_any / Any_convert_extern) instead of generic ref_cast where needed.
1 parent 3979aac commit f2811ac

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

src/clam_of_core.ml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,28 @@ let rec transl_expr ~name_hint ~mtype_defs ~addr_tbl ~type_defs ~object_methods
250250
| Ref _ | Ref_lazy_init _ | Ref_nullable _ | Ref_extern
251251
| Ref_string | Ref_bytes | Ref_func | Ref_any ->
252252
Prefeq)
253+
| Pidentity -> (
254+
match[@warning "-fragile-match"] args with
255+
| arg :: [] ->
256+
let source_type = transl_type (Mcore.type_of_expr arg) in
257+
let target_type = transl_type ty in
258+
if Ltype.equal source_type target_type then go arg
259+
else
260+
bind arg (fun source ->
261+
Lcast { expr = Lvar { var = source }; target_type })
262+
| _ -> assert false)
253263
| Pcast { kind } -> (
254264
match[@warning "-fragile-match"] args with
255265
| arg :: [] -> (
256266
match kind with
257267
| Constr_to_enum | Make_newtype -> go arg
258268
| Unfold_rec_newtype | Enum_to_constr ->
269+
let source_type = transl_type (Mcore.type_of_expr arg) in
259270
let target_type = transl_type ty in
260-
Lcast { expr = go arg; target_type })
271+
if Ltype.equal source_type target_type then go arg
272+
else
273+
bind arg (fun source ->
274+
Lcast { expr = Lvar { var = source }; target_type }))
261275
| _ -> assert false)
262276
| Penum_field { index; tag = _ } -> (
263277
let tid =

src/wasm_of_clam_gc.ml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ let addr_to_string = Basic_fn_address.to_wasm_name
9595
let add_cst = Wasmir_util.add_cst
9696
let add_dummy_i32 rest = add_cst 0 rest
9797

98+
let cast_operand_type (e : Clam.lambda) =
99+
match Clam_util.no_located e with
100+
| Lvar { var } -> Some (Ident.get_type var)
101+
| Lcast { target_type; _ } -> Some target_type
102+
| _ -> None
103+
98104
type loop_info = { params : Ident.t list; break_used : bool ref }
99105

100106
type ctx = {
@@ -574,9 +580,16 @@ and compileExpr0 ~(tail : bool) ~ctx ~global_ctx ~type_defs (body : Clam.lambda)
574580
let tid_base = tid in
575581
generic_get var @> struct_get tid_base 0 @: generic_get var
576582
@> call closure_ffi_name @: rest
577-
| Lcast { expr; target_type = Ref_any } -> got expr rest
578-
| Lcast { expr; target_type } ->
579-
gon expr (ref_cast (result target_type) @: rest)
583+
| Lcast { expr; target_type = Ref_any } -> (
584+
match cast_operand_type expr with
585+
| Some Ref_extern -> gon expr (Ast.Extern_convert_any @: rest)
586+
| _ -> got expr rest)
587+
| Lcast { expr; target_type = Ref_extern } -> (
588+
match cast_operand_type expr with
589+
| Some Ref_any -> gon expr (Ast.Any_convert_extern @: rest)
590+
| _ -> gon expr (ref_cast (result Ref_extern) @: rest))
591+
| Lcast { expr; target_type } ->
592+
gon expr (ref_cast (result target_type) @: rest)
580593
| Lcatch { body; on_exception; type_ } ->
581594
assert !Basic_config.test_mode;
582595
let body = gon body [] in

0 commit comments

Comments
 (0)