20260921 MoonBit v0.10.14
对应 moonc 版本:v0.10.14
语言更新
新增 MySubError::_ 模式匹配
支持使用 T::_ 按类型匹配子错误,无需逐一列举该类型的错误构造器。并且该特性可以用于把 Error 类型 narrow 到具体的子错误类型。
suberror ParseError {
Empty
InvalidChar(Char)
}
fn describe(error : Error) -> String {
match error {
ParseError::_ as e => use_suberror(e) // type of e is ParseError
_ => "其他错误"
}
}
fn use_suberror(_e: ParseError) -> String {
"解析错误"
}
fn main {
println(describe(ParseError::Empty)) // 解析错误
println(describe(ParseError::InvalidChar('?'))) // 解析错误
}
for... in... 支持模式匹配
for... in... 循环现在可以直接解构迭代元素:
fn main {
let items = [("苹果", 2), ("梨", 3)]
for (name, count) in items {
println("\{name}: \{count}")
}
// 输出:
// 苹果 : 2
// 梨 : 3
}
enum 新增 #non_exhaustive 标记
有 #non_exhaustive 标记的 enum 在未来可能添加新的构造器,因此匹配一个来自外部的、 有 #non_exhaustive 标记的 enum 时,在匹配完所有已知的构造器之后,还需要用 TypeName::.. 的形式处理未来潜在的未知构造器,否则编译器会给出警告:
// @pkg
#non_exhaustive
enum E {
A
B
}
// 在另一个包内:
fn bad(x : @pkg.E) -> Unit {
// 编译器会给出警告:匹配 `#non_exhaustive` 的 enum 需要处理未知构造器
match x {
A | B => ...
}
}
fn good(x : @pkg.E) -> Unit {
match x {
A | B => ...
E::.. => println("fallback")
}
}
E::.. 是一个专门用来处理未知构造器的构造。因此,使用 E::.. 时,如果还有未匹配的已知构造器,编译器同样会给出警告。例如,如果 @pkg 给 E 加上了一个新的构造器 C,那么 good 函数内的模式匹配就会收到一个警告,告诉用户有未匹配的已知构造器 C 。这样一来,下游就可以通过警告收到上游新增构造器的通知。在运行时,E::.. 会匹配任何值。因此在 good 适配新的构造器 C 之前,C 会由 E::.. 的默认分支处理,而不会使程序崩溃。
如果只想匹配某个 #non_exhaustive 类型中的少数特殊构造器,可以使用 _ 。_ 即使在已知构造器未全部匹配时也可以使用,表示显式忽略剩余的所有构造器。不过,如果在已知构造器已全部匹配的情况下使用 _,编译器会给出警告提示用户改用 E::..,因为上游新增构造器后, 只有 E::.. 能收到通知
管道表达式改进
lhs |> x => {...} 右侧的匿名函数体支持调用异步函数:
.mbtx 脚本
import {
"moonbitlang/async@0.21.3",
}
async fn main {
let result = 21 |> value => { @async.sleep(1); double(value) }
println(result) // 42
}
切片 a[i:j] 改进
切片 a[i:j] 改为自动限制边界的视图(clamped view),切片范围会限制在有效边界内。
fn main {
let values = [10, 20, 30]
let middle = values[1:10] // 实际范围是 [1:3] ,包含 20 、 30
println(middle.length()) // 2
println(middle[0]) // 20
println(values[5:10].length()) // 0 ,得到空视图
}
这里的主要动机是 a[i:j] 确保不会在运行时 crash,包括对 String 取视图时使用位于 UTF16 surrogate 边界上的非法下标的情况。如果需要使用之前可能会 crash 版本的取视图操作,需要使用新加的 exact_view API
改进未使用包的警告。下列两种情况现在会收到警告:
-
显式
import了moonbitlang/core中的包但没有使用 -
没有通过
@xxx.xxx的形式显式使用一个import,仅通过调用方法等形式间接地使用了import的包的内容
这两种情况里,import 都是不必要的,但之前编译器不会给出警告。现在编译器能对这两种情况也给出警告了。例如,普通包中的以下配置和代码会使 moon check 报告 unused_package,删除未使用的 math 导入即可消除警告。
import {
"moonbitlang/core/math", // 本包没有使用它,可删除此导入
}
fn main {
println("Hello, MoonBit!")
}
针对 var x = 10 的错误恢复改进
改进对 var 声明(含类型标注)的诊断,识别后给出警告,提示改用 let mut 。
fn main {
var count = 0 // 警告:改用 let mut
count += 1
println(count)
}
Deprecate 在 JavaScript FFI 边界上使用 Array
后续版本中会调整 MoonBit Array 在 JavaScript 后端的 ABI,不再保证其等价于 JavaScript 后端的 Array,所以在 FFI 边界上使用 Array 被 deprecate 了,需要使用 FixedArray 替代
默认开启 impl 自动提升为方法的警告
之前,和类型定义在同一个包里的 impl 会自动被转换成方法,方便用户通过 . 调用。我们计划废弃这一行为,转而要求显式使用 extend Type with Trait::{f, g} 语法来将 impl 变为方法。编译器提供了一个警告,会对所有按当前语义自动提升为方法的 pub impl 发出警告,提示用户用 extend 进行迁移。具体的迁移方式是:
-
如果希望保留对应的方法,直接添加一个
extend声明即可。 -
如果希望废弃对应的方法,仍需添加一个
extend声明,但可以将该声明标记为#deprecated。
之前,该警告默认关闭。本次更新后,该警告默认开启,所有用户都应当进行迁移。关于迁移的更多细节,详见 2026/07/13 的月报。
默认开启黑盒测试自动引入定义的警告
在 MoonBit 中,黑盒测试(_test.mbt 文件)用于测试某个包的公开 API,因此测试自身是一个独立的包,引用被测试的 API 时应通过 @pkg.xxx 的形式显式调用。之前,为了简化测试,编译器会在黑盒测试中自动导入被测试包的全部定义,除非该定义被测试内部的本地定义覆盖。这一行为较为隐式,因此我们不再鼓励使用这一功能。编译器提供了 test_unqualified_package 警告,会在依赖上述自动导入功能的 地方发出警告。之前,该警告默认关闭,本次更新后默认开启。
工具链更新
Moon 与运行时
-
新增
moon search,用于查询包,比如moon search 'html markdown'可以用于查找和 html markdown 相关的包 -
新增
moon view,用于查看包的版本、某位用户发布的包等信息,如moon view --my或moon view moonbitlang/async --versions -
新增
moon deprecate,用于标记某个包为弃用;暂不支持对特定版本进行处理 -
moon tree [--json]输出模块外部依赖,moon tree --package [--json]输出包依赖 -
moonx将聚焦 Wasm 后端执行,--target native已被废弃 -
moonx执行策略支持按命令前缀生成进程 -
moonx执行策略可在moonx调用之间继承 -
moonx支持运行.mbtx文件 -
.mbtx文件实验性支持在文件头声明所需权限,并由运行时限制,如:
// policy:
// fs:
// read: []
///|
import {
"moonbitlang/async@0.21.3",
"moonbitlang/async@0.21.3/fs",
}
///|
async fn main {
// Following operation will be rejected
println(@fs.read_file("input.txt").text())
}
-
moon runwasm已被废弃 -
实验性预构建脚本支持
.mbtx,并增加脚本可接收的环境变量;原有的通过 stdin 方式的输入将会移除 -
实验性预构建脚本限制在 native 后端运行。
编辑器支持
-
语言服务支持在同一工作区中同时处理多个后端。
-
moon ide支持.mbtx文件,并修复脚本同级目录存在moon.pkg时导入别名可能被覆盖的问题。
标准库更新
moonbitlang/core
-
QuickCheck 增加无偏随机数生成支持,改进标量
Arbitrary的生成范围和边界值覆盖;BigInt生成器不再局限于 64 位,可以生成更大范围的数值及常见边界值,并补充收缩器的统一入口。 -
新增
derive(Shrink),可自动生成反例收缩逻辑,帮助找到更小、更简单的失败用例;当前尚不支持基于子项的收缩。 -
为
BigInt增加使用宽位算 术的 native 和 wasm1 后端实现;修复immut/vector中的多个溢出问题。 -
调整
Array的遍历与清理行为:遍历时先取得底层缓冲区;pop、truncate、clear等操作先调整长度,原槽位仍可能保留元素引用。新增fill_unused,可通过填充默认值释放这些引用。 -
增加百分号编码辅助函数,将字符编码为 %XX 形式。
moonbitlang/x
-
补全并优化
crypto。 -
新增
jwt包,支持 HS256 编码和解码。 -
新增密码哈希包
bcrypt。 -
统一 Unicode 实现到
moonbitlang/x/unicode,旧 API 标记为弃用。
moonbitlang/async
moonbitlang/async 目前最新版本为 0.22.1,自上次月报(0.21.0)以来的主要更新有:
-
[breaking] 取消语义调整。之前,当一个异步任务被取消时,它会收到一个特殊的
suberror作为信号,以便被取消的代码进行清理。现在,取消信号不再是一个suberror,而是通过特殊的编译器原语实现,相比suberror:-
新的取消信号依然会像错误一样,自动向上传播
-
取消信号可以触发
defer与errdefer -
新的取消信号不能被
catch捕获
-
用户代码的迁移方式可参考 https://github.com/moonbitlang/async/releases/tag/v0.22.0
-
[breaking]
@async.is_cancellation_error现在只会返回false且被废弃。因为取消信号不再是一个特殊错误了。对于使用了@async.is_cancellation_error来特殊处理取消信号的catch,如果取消相关的分支的作用是跳过对取消信号的处理,可以直接删除对应分支。否则,可以使用@async.handle_cancellation来对取消信号进行特殊处理 -
一些 API 获得了更精确的类型。由于取消不再是一个特殊错误,在类型层面,可取消与
raise也不再绑定了。在最新版本中,async函数默认都是可取消的,只有显式添加了nocancel标记的异步函数,例如@async.protect_from_cancel,才是不可取消的。同时,一些自身不会抛出错误但可以被取消的异步函数,例如@async.sleep,现在可以在签名里写上noraise了 -
[breaking]
@async.TaskGroup::add_defer现在要求传入的回调函数必须是nocancel的 -
@async.with_cancellation_handler被废弃,由一个新的 API@async.handle_cancellation替代。@async.handle_cancellation会运行一个异步的回调函数(运行时这个异步函数依然是可取消的),并在回调函数被取消时返回None。它可以用于对取消进行特殊处理。 需要注意@async.handle_cancellation不能撤掉当前任务被取消的状态。即使捕获一次取消信号,当前任务后续的可取消异步操作依然会被马上取消 -
@fs.remove和@fs.rmdir变为不可取消(nocancel) -
@socket.TcpServer(..)新增了reuse_port_lb?: Bool = false选项,开启后该 TCP 服务器可以和其他服务器共享同一个监听地址,内核会自动在共享同一个端口的服务器间进行负载均衡。该选项仅支持 Linux,在其他操作系统上会被无视 -
新增了
@async.platform,可以用于在运行时判断当前操作系统。由于同一份 Wasm 二进制可以在不同的操作系统上运行,对于 Wasm 后端的程序,当前操作系统只能在运行时获得, 无法在编译期判断
生态与开发工具更新
mooncakes.io 包管理服务
-
搜索服务正式上线,加入包摘要索引和已有包的预索引。
-
支持通过
moon deprecate弃用模块,网站会展示弃用状态及原因。 -
改进构建队列的构建速度。
SeekMoon
-
增加 web search 和 mbtx 工具。mbtx 工具允许智能体在沙箱中运行 mbtx 脚本。改进了 edit 工具失败时的错误报告。
-
增加了 SSE 断流时候的重试功能,减少网络波动导致的智能体运行中止。
-
集成了基于 MoonBit token 和 AST 的 diff 算法,支持忽略测试和注释差异。支持块级别的跳转和标记为已查看。增 加 Git 提交历史。
-
支持将
.mbti渲染为 SVG,以及从moon.mod展示项目依赖图。 -
集成 rg 文本搜索和 moongrep 搜索。moongrep 查询 pattern 可通过 AI 修复。
-
增加右键菜单,Cmd+W 关闭标签,改进选中文本高亮,以及字体等 UI 上面的改进。
-
改进 Windows 支持。
-
cmd/openseek支持在 Wasm 上运行。
Rabbita 与全栈开发
提供网页、桌面与后端的 MoonBit 全栈模板,调试和打包开箱即用,无需 Makefile 或其他语言脚本:https://github.com/moonbit-community/fullstack-moonbit。
Proton
-
桌面端开发框架 proton 以 Apache 2.0 协议开源 https://github.com/moonbit-community/proton
-
现已支持国际化、应用图标角标、右键菜单及无障碍。
Moonback
Web 后端框架 Moonback 现以 Apache 2.0 协议开源,并移动到 moonbitlang/moonback。 mooncakes.io 网站后端现在 powered by moonback。
cli 命令工具
cli/<cmd> 在 mooncakes 发布,收录 moonbit-jq 已迁移的命令,并持续迁移常用命令、完成跨平台验证;0.1.2〜0.1.4 更新补齐常用参数,修复与上游工具不一致的行为。
moonbit-community/sqlite3
增加实验性的异步支持,包括 native 和 wasm 后端