20260310 MoonBit v0.8.3
发布于: 2026年3月10日
语言更新
-
使用
#alias和#as_free_fn标记的函数,将不再继承不应该继承的属性,如#deprecated属性。现在,#alias声明的别名和函数本体的各种属性都可以独立地控制:// 本体和别名都不 deprecate #alias(g1) fn f1() -> Unit // 只 deprecate 别名 #alias(g2, deprecated) fn f2() -> Unit // 只 deprecate 本体 #alias(g3) #deprecated fn f3() -> Unit // 本体和别名都 deprecate #alias(g4, deprecated) #deprecated fn f4() -> Unit -
const声明支持了字符串拼接和字符串插值:const Hello : String = "Hello" const HelloWorld : String = Hello + " world" const Message : String = $|======== $|\{HelloWorld} $|======== -
让
for .. in循环支持了额外的循环变量:// 对数组 xs 求和 for x in xs; sum = 0 { continue sum + x } nobreak { sum }利用这一新特性,
for .. in循环可以用函数式的方式维护额外的状态,无需使用let mut -
废弃无方法类型被所有类型隐式实现的行为。 之前,一个没有任何方法的
trait会被所有类型隐式实现,无需显式写impl Trait for Type。这一行为已被废弃,使用这种隐式的实现时会收到警告。未来,这一行为将被彻底移除,届时所有trait都统一需要显式实现 -
废弃
for { ... }无限循环的用法。之前,可以使用for { ... }来写一个没有终止条件的无限循环。这一语法已被废弃,需要将循环写成for ;; { ... }或while true { ... }。这一改动可以使用moon fmt自动完成迁移。这一改动的动机是:我们未来可能会为for .. in循环添加模式匹配的支持,如for (x, y) in array_of_tuple。而for { .. }语法和模式匹配struct或Map有语法冲突 -
无更新部分的for循环允许省略分号。
for i = 0; i < 10; { ... }(没有更新部分)的for循环,现在可以省略循环条件后的分号,写成for i = 0; i < 10 { ... } -
正式移除
impl总是可以通过.调用的行为。 在 MoonBit 中,只有当impl和类型定义在同一个包内时,impl才可以通过x.f(..)语法调用。但在 MoonBit beta 版本前,当前包内的impl总是可以通过.调用。这一行为已在 beta 版本以警告的形式废弃,现在,这一行为被正式移除 -
FFI 参数未标注生命周期管理方式默认状态下变成了一个错误而非警告。未来,我们将正式把FFI 参数默认的生命周期管理方式从
#owned改为#borrow, 当前未标注生命周期管理方式的FFI函数,编译器将会报一个错误。 -
修复了
for i in x..<y循环的nobreak块中依然可以引用循环变量i的问题。一些意外依赖了这一行为的代码可能会编译失败。 -
改进了一些顶层函数签名不匹配的错误信息,在错误信息中只输出签名不一样的部分,方便定位错误。例如:
trait I { f(Self, flag1~ : Int, flag2~ : Int, flag3~ : Int) -> Unit } impl I for T with f(self, flag1~, flga2~, flag3~) { ... }原本的报错信息是:
... expected: (Self, flag1~ : Int, flag2~ : Int, flag3~ : Int) -> Unit actual: (Self, flag1~ : Int, flga2~ : Int, flag3~ : Int) -> Unit改进后的报错信息是:
... expected: (.., flag2~ : _, ..) -> Unit actual: (.., flga2~ : _, ..) -> Unit -
新增了
#unsafe_skip_stub_check属性,它可以用于跳过 FFI 签名中对类型是否具有稳定 ABI 的检查。该属性可以用于高级用户在 wasm 后端进行较复杂的 FFI 实验。需要注意,跳过检查后 FFI 的行为是未定义的且随时可能发生变动,因此该属性只应用于实验
工具链更新
-
moon ide新增analyze命令用于分析一个包的公开API的使用情况。它会以mbti的格式将一个包的公开API打印出来,并在每个API的后面用注释写明它的使用情况,包括总使用次数,在测试中的使用次数和该API是否在exports.mbt中被定义。下面是一个输出的例子:$ moon ide analyze . # path to packages to be analyzed package "username/analyze" import { "username/analyze/util", } // Values pub const REPORT_CONST_TAG : String = "analyze-tag" // usage: 2 (1 in test) #alias(analyze_raw) // usage: 2 (1 in test) pub fn analyze_text(String) -> @util.Token // usage: 2 (1 in test) pub fn build_report(String, @util.Level) -> Report // usage: 2 (1 in test), in exports.mbt pub fn never_called_pub() -> String // usage: 0 (0 in test), in exports.mbt // Errors // Types and methods pub(all) struct Report { title : String // usage: 1 (0 in test) score : Int // usage: 1 (0 in test) fn new(String, Int) -> Report // usage: 2 (1 in test) } #as_free_fn(make_report) // usage: 2 (1 in test) pub fn Report::new(String, Int) -> Self // usage: 0 (0 in test) pub impl Analyzer for Report // usage: 2 (1 in test) // Type aliases pub using @util {type Token as PublicResult} // usage: 0 (0 in test) // Traits pub trait Analyzer { analyze(Self, String) -> @util.Token // usage: 2 (1 in test) }moon ide analyze两种参数传递方式:-
moon ide analyze分析当前模块中所有的包 -
moon ide analyze path/to/pkg1 path/to/pkg2 ...分析所有传入的包,可以和shell中的glob pattern配合使用,例如moon ide analyze internal/*可以用来分析所有internal的包。
这个命令可以配合 AI 重构,快速删除模块内未使用的公开 API。不过,由 于非
internal包的公开 API 可能被模块外用户使用,这种重构原则上只对internal包安全。为了区分非internal包中“对内使用”和“对外使用”的 API,我们引入了一项约定:凡是预期供模块外用户使用的公开 API,都应定义在exports.mbt中。对于这类 API,即使模块内没有任何使用,也不应删除。moon ide analyze会在输出中对exports.mbt中定义的 API 进行特别标注,例如build_report和never_called_pub。 -
-
supported-targets支持完善-
启用新语法,可通过"+js+wasm+wasm-gc"显式声明支持哪些后端,或用"+all-js"表示不支持哪些后端
-
在
moon.mod.json与moon.pkg中均可定义,对一个包来说,支持后端为两者交集 -
当无法构造依赖图时,有更好的错误信息
-
-
构建系统现在会追踪编译器,以减少由于编译器版本更新、缓存不匹配导致的 segfault 行为
-
mbtx脚本模式支持从stdin输入$ echo "fn main {println(\"hello\")}" | moon run -$ moon run - <<EOF import { "moonbitlang/core/list" } fn main { debug(@list.from_array([1, 2, 3])) } EOF
标准库更新
-
增加
argparse库,提供基础的命令行参数解析功能///| async fn main { let cmd = @argparse.Command("demo", options=[@argparse.OptionArg("name")], positionals=[ @argparse.PositionArg("target"), ]) let _ = cmd.parse() } -
moonbitlang/async更新:-
JavaScript 后端添加了基于
fetchAPI 的 HTTP client 支持。moonbitlang/async/http中的所有 HTTP client API(除 HTTP proxy 支持)均在 JavaScript 后端可用(包括浏览器环境) -
moonbitlang/async/js_async添加了与 WebAPIReadableStream交互的支持
-