20260310 MoonBit v0.8.3 Release
Language Updates
-
Functions marked with
#aliasand#as_free_fnwill no longer inherit attributes that they should not inherit, such as the#deprecatedattribute. Now, the alias declared by#aliasand the various attributes on the original function body can be controlled independently:// Neither the original nor the alias is deprecated #alias(g1) fn f1() -> Unit // Only the alias is deprecated #alias(g2, deprecated) fn f2() -> Unit // Only the original is deprecated #alias(g3) #deprecated fn f3() -> Unit // Both the original and the alias are deprecated #alias(g4, deprecated) #deprecated fn f4() -> Unit -
constdeclarations now support string concatenation and string interpolation:const Hello : String = "Hello" const HelloWorld : String = Hello + " world" const Message : String = $|======== $|\{HelloWorld} $|======== -
for .. inloops now support additional loop variables:// Sum the array xs for x in xs; sum = 0 { continue sum + x } nobreak { sum }With this new feature,
for .. inloops can now maintain extra state in a functional style without usinglet mut. -
Deprecate implicit implementation of method-less traits.Previously, a trait with no methods was implicitly implemented by all types, without requiring an explicit
impl Trait for Type. This behavior has now been deprecated, and using such implicit implementations will produce a warning. In the future, this behavior will be removed entirely, and all traits will uniformly require explicit implementation. -
Deprecate
for { ... }infinite loop syntax.Previously,for { ... }could be used to write an infinite loop with no termination condition. This syntax has now been deprecated. Such loops should instead be written asfor ;; { ... }orwhile true { ... }. This migration can be performed automatically usingmoon fmt. The motivation for this change is that we may add pattern matching support tofor .. inloops in the future, such asfor (x, y) in array_of_tuple. Thefor { .. }syntax conflicts syntactically with pattern matching on structs orMaps. -
Allow omitting the semicolon in
forloops without an update clause.Forforloops such asfor i = 0; i < 10; { ... }(with no update clause), the semicolon after the loop condition can now be omitted, so it can be written asfor i = 0; i < 10 { ... }. -
Remove the behavior allowing impl to always be called via
.In MoonBit, animplcan only be called usingx.f(..)syntax when both theimpland the type definition are in the same package. However, before the MoonBit beta release,implsin the current package could always be called using.syntax. This behavior was deprecated with a warning in the beta release, and has now been officially removed. -
FFI parameters without an explicitly annotated lifetime management mode are now treated as an error rather than a warning. In the future, we will officially change the default lifetime management mode for FFI parameters from
#ownedto#borrow. For now, the compiler will report an error for any FFI function whose lifetime management mode is not explicitly annotated. -
Fix referencing loop variable
iinnobreakblocks offor i in x..yloops.Fixed an issue where the loop variable i could still be referenced inside the nobreak block of afor i in x..<yloop. Some code that accidentally relied on this behavior may now fail to compile. -
Improve error messages for mismatched top-level function signatures. Improved some error messages for mismatched top-level function signatures: the error output now shows only the differing parts of the signature, making it easier to locate the problem. For example:
trait I { f(Self, flag1~ : Int, flag2~ : Int, flag3~ : Int) -> Unit } impl I for T with f(self, flag1~, flga2~, flag3~) { ... }Previously, the error message was:
... expected: (Self, flag1~ : Int, flag2~ : Int, flag3~ : Int) -> Unit actual: (Self, flag1~ : Int, flga2~ : Int, flag3~ : Int) -> UnitThe improved error message is now:
... expected: (.., flag2~ : _, ..) -> Unit actual: (.., flga2~ : _, ..) -> Unit -
Added the
#unsafe_skip_stub_checkattribute, which can be used to skip checks on whether types in an FFI signature have a stable ABI. This attribute can be used by advanced users for more complex FFI experiments on the wasm backend. Note that once this check is skipped, FFI behavior becomes undefined and may change at any time, so this attribute should only be used for experimentation.
Toolchain Updates
-
moon idenow includes a newanalyzecommand for analyzing usage of a package’s public APIs. It prints the package’s public APIs inmbtiformat, and appends a comment to each API showing its usage information, including total usage count, usage count in tests, and whether the API is defined inexports.mbt. Below is an example of the output:$ 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 analyzesupports two ways of passing arguments:moon ide analyzeanalyzes all packages in the current module.moon ide analyze path/to/pkg1 path/to/pkg2 ...analyzes all specified packages, and can be used together with shell glob patterns. For example,moon ide analyze internal/*can be used to analyze all packages underinternal.
This command can be used together with AI-powered refactoring to quickly remove unused public APIs within a module. However, since the public APIs of non-
internalpackages may be used by users outside the module, this kind of refactoring is, in principle, only safe forinternalpackages. To distinguish between APIs in non-internalpackages that are intended forinternaluse and those intended for external use, we have introduced a new convention: any public API intended for users outside the module should be defined in exports.mbt. Such APIs should not be removed, even if they have no usage within the module.moon ide analyzewill specially highlight APIs defined inexports.mbtin its output, such asbuild_reportandnever_called_pub -
Support for
supported-targetshas been improved. The new syntax is now enabled, allowing users to explicitly declare which backends are supported using forms like"+js+wasm+wasm-gc", or to declare which backends are not supported using"+all-js".This can be defined in both
moon.mod.jsonandmoon.pkg. For a given package, the supported backends are the intersection of the two.Better error messages are now provided when a dependency graph cannot be constructed.
-
The build system now tracks the compiler itself, reducing
segfaultissues caused by compiler version updates and cache mismatches. -
The
mbtxscript mode now supports input fromstdin:$ echo "fn main {println(\"hello\")}" | moon run -$ echo "fn main {println(\"hello\")}" | moon run - $ moon run - <<EOF import { "moonbitlang/core/list" } fn main { debug(@list.from_array([1, 2, 3])) } EOF
Standard Library Updates
-
Added the
argparselibrary, which provides basic command-line argument parsing:///| async fn main { let cmd = @argparse.Command("demo", options=[@argparse.OptionArg("name")], positionals=[ @argparse.PositionArg("target"), ]) let _ = cmd.parse() } -
Updates to
moonbitlang/async:The JavaScript backend now includes HTTP client support based on the Fetch API. All HTTP client APIs in
moonbitlang/async/httpare available on the JavaScript backend except HTTP proxy support, including in browser environments.moonbitlang/async/js_asyncnow includes support for interacting with the Web APIReadableStream.