You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何理解Wasm递归类型及两段代码的差异与报错问题

WebAssembly GC:非rec包裹类型与rec包裹类型的差异及类型验证报错解析

一、两段基础代码的差异

WebAssembly GC规范中,rec块的核心作用是声明互递归/自递归的类型组——当一组类型之间存在互相引用(比如A引用B、B同时引用A),或者单个类型自引用时,必须用rec包裹,让这些类型处于同一个作用域中,解决引用顺序的问题。

  • 第一段代码(无rec):

    (module
      (type $f1 (func)) 
      (type (struct (field (ref $f1))))
    )
    

    这是顺序依赖声明:$f1先定义,后面的struct类型仅引用已经存在的$f1,不存在反向引用或递归,完全符合规范的非递归类型声明规则,因此Binaryen可以正常编译。

  • 第二段代码(有rec):

    (module
      (rec
        (type $f1 (func)) 
        (type (struct (field (ref $f1))))
      )
    )
    

    这里用rec包裹两个类型,虽然实际不存在互递归,但规范允许rec包裹非递归的类型组(只是没必要)——rec块内的所有类型会被视为同时定义、互相可见,因此这段代码同样合法,可正常编译。

二、报错代码的问题原因

报错的核心是引用类型不匹配,和rec本身的语法无关:

(module
  (type $f1 (func)) 
  (type (struct (field (ref $f1))))
  (rec (type $f2 (func)) (type (struct (field (ref $f2)))))
  (func $f (type $f2))
  (global (ref $f1) (ref.func $f))
)
  1. $f1和$f2是两个独立的函数类型定义:即使它们的结构完全相同(都是无参无返回的函数类型),在WebAssembly的类型系统中,它们是不同的名义类型,对应的ref $f1和ref $f2是两种不兼容的引用类型。
  2. func $f的类型是$f2,因此(ref.func $f)生成的值的类型是ref $f2,但全局变量声明的类型是ref $f1,类型不匹配,触发验证错误:global init must have correct type。

简言之,你试图把ref $f2类型的函数引用赋值给要求ref $f1类型的全局变量,二者类型不兼容导致报错。

内容的提问来源于stack exchange,提问作者Jason Yu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 08:43:33