20251202 MoonBit Monthly Update Vol.06
Version 0.6.33
Language Update
-
Improved functionality for
ReadOnlyArray.ReadOnlyArraywas introduced in the previous version, primarily used for declaring lookup tables, and the compiler performs more performance optimizations forReadOnlyArray. In this version, the feature support forReadOnlyArrayhas been improved to provide a user experience basically consistent with other array types, such as pattern matching, slicing, and spread operations.fn main { let xs: ReadOnlyArray[Int] = [1,2,3] let _ = xs[1:] match xs { [1, .. rest] => ... ... } let _ = [..xs, 1] } -
bitstring pattern supports signed extraction, allowing the extracted bits to be interpreted as signed integers, for example:
fn main { let xs : FixedArray[Byte] = [0x80, 0, 0, 0] match xs { [i8be(i), ..] => println(i) // prints -128 because 0x80 is treated as signed 8-bit int _ => println("error") } } -
Cascade function call improvements
Previously, in cascade-style function calls like
x..f()..g(), the return type offwas required to beUnit. This restriction has now been removed. Whenfreturns a value of a type other thanUnit, aninvalid_cascadewarning will be triggered, and at runtime this return value will be implicitly discarded:struct Pos {} fn Pos::f(_ : Self) -> Int { 100 } fn Pos::g(_ : Self) -> Unit { () } fn main { let self = Pos::{} self ..f() // warning, discard the returned value 100 ..g() }If you wish to prohibit such implicit discarding in your project, you can treat this warning as an error by configuring
"warn-list": "@invalid_cascade". -
Syntax parsing improvements
- Improved error recovery when
::is omitted inStructName::{ field1: value } - Improved error recovery when range syntax is incorrectly written in
for x in a..=b {}andmatch e1 { a..=b => e2 }
- Improved error recovery when
-
Improvements to
.mbt.mdcode block support We have decided to make markdown code blocks that participate in compilation more explicit. The specific changes are as follows:-
Code blocks marked only as
mbtormoonbitwill no longer be compiled. These code blocks need to be explicitly marked ascheck, i.e.,mbt checkor moonbit check, to be compiled as before. -
Added
mbt testandmbt test(async)code blocks. In addition to participating in compilation, these code blocks will also wrap the code in a test orasync testblock. When using these two types of code blocks in markdown, users no longer need to manually writetest {}orasync test.# A Markdown Example Highlighting only: ```mbt fn f() -> Unit ``` Highlighting and checking: ```mbt check fn f() -> Unit {...} ``` Highlighting, checking and treated as a test block: ```mbt test inspect(100) inspect(true) ```
The markdown in docstrings has also undergone the same changes, although
mbt checkis not currently supported but will be supported in the future. -
-
#label_migrationattributeThe
#label_migrationattribute supports declaring aliases for parameter labels, with two main uses: first, it allows giving the same parameter two different labels; second, when an additional msg is provided, it can be used to deprecate a certain parameter label:#label_migration(x, alias=xx) #label_migration(y, alias=yy, msg="deprecate yy label") fn f(x~ : Int, y? : Int = 42) -> Unit { ... } ///| fn main { f(x=1, y=2) // ok f(xx=1, yy=2) // warning: deprecate yy label f(x=1) // ok } -
#deprecateddefault behavior improvementThe default behavior of
deprecatedhas been changed toskip_current_package=false, meaning warnings will also be reported for usage within the current package. If unexpected warnings appear in recursive definitions or tests, you can explicitly disable warnings for the current package using#deprecated(skip_current_package=true), or use the newly added#warningsattribute to temporarily disable warnings. -
Warnings and alerts improvements
-
Added mnemonics for warnings
Now you can configure warnings by their names instead of numbers:
"warn-list": "-unused_value-partial_match" -
#warningsattribute supportNow supports locally enabling/disabling warnings through the
#warningsattribute. The parameter inside the attribute is the same string format as thewarn-listconfiguration. The string contains multiple warning names, each preceded by a symbol indicating the configuration for that warning:-namemeans disable the warning;+namemeans enable the warning;@namemeans if the warning is already enabled, escalate it to an error.For example, the following example disables the
unused_valuewarning for the entire functionfand escalates the default-enableddeprecatedwarning to an error. Now it won't prompt that the variable is unused, but iffuses a deprecated API, compilation will fail:#warnings("-unused_value@deprecated") fn f() -> Unit { let x = 10 }Currently, this attribute only supports configuring certain specific warnings.
-
Merge alerts and warnings
Deprecate alerts-related configurations. Now alerts have become a subset of warnings. When using -a to disable all warnings, all alerts will also be disabled. Specifically, in warn-list, you can use alert to refer to all alerts, and alert_<category> to refer to a specific category of alerts:
#warnings("-alert") fn f() -> Unit { ... } //Disable all alert warnings #warnings("@alert_experimental") fn g() -> Unit { ... } //Related to APIs marked with #internal(experimental, "...") -
test_unqualified_packagewarningAdded the
test_unqualified_packagewarning, which is disabled by default. When enabled, it requires blackbox tests to reference the tested package's API using the@pkg.nameformat, otherwise this warning will be triggered.
-
-
Lexmatch syntax update
The experimental
lexmatchexpression now supports thefirst(default) matching strategy. Under this matching strategy,searchmode and non-greedy quantifiers are supported. For specific details, please refer to the proposal.// Find the first block comment and print its content lexmatch s { // `with first` can be omitted (_, "/\*" (".*?" as content) "\*/", _) => println(content) _ => () } -
Type inference improvements
Fixed the issue where type information in
Xcould not propagate to expressions when the expected type isArrayView[X], and the issue where type parameters could not propagate to expressions when the expected type is a newtype with parameters. -
Added #module attribute for importing third-party JS modules For example, the following code imports the third-party JS module "path" and uses "dirname" from that module
#module("path")
extern "js" fn dirname(p : String) -> String = "dirname"
The code above will result in the following generated JS code (simplified, the actual code has name mangling):
import { dirname } from "path";
Toolchain Update
-
IDE completion improvements
The IDE now displays deprecated APIs with strikethrough formatting:

-
Build system improvements
- Enhanced the readability of expect/snapshot test diffs. Now, these areas use the unified diff format to display the differences between expected and actual values, making them readable even in scenarios where colors are not output, such as in CI and files, while still showing colored and highlighted comparison results when color display is available.

- Enhanced the readability of expect/snapshot test diffs. Now, these areas use the unified diff format to display the differences between expected and actual values, making them readable even in scenarios where colors are not output, such as in CI and files, while still showing colored and highlighted comparison results when color display is available.
-
New Build system backend
We have basically completed a complete rewrite of the build system backend, which can be enabled for trial use through the
NEW_MOON=1environment variable.The new backend is less prone to errors due to various edge cases during the build process, offering stronger stability, while also providing performance improvements compared to the current implementation. The new backend now supports the vast majority of existing features and behaves exactly the same as the current implementation, but may lack some optimizations in certain situations (such as running tests in parallel).
If you encounter any issues when running the new backend, including performance issues and behavioral inconsistencies, please report them at https://github.com/moonbitlang/moon/issues.
-
File path-based filtering for
moon {build,check,info}moonbuild#1168.When running
moon build,moon check, ormoon info, you can pass in the folder path where the package to be processed is located or a file path within it, and only the corresponding command for that package will be executed. This usage is similar to-p <package name>, but doesn't require entering the complete package name. This feature cannot be used simultaneously with-p. For example:# Build only the package at path/to/package moon build path/to/package # Check only the file at path/to moon check path/to/file.mbt -
moon docsymbol lookup We have created a symbol search command-line tool similar togo doc, making it convenient for AI agents or developers to quickly search for available APIs. Currently supports the following features:- Query available packages in a module
- Query all available items (values, types, traits) in a package
- Query members of a type (method, enum variant, struct field, trait method)
- Follow aliases to their final definition when querying
- Query built-in types
- Support glob patterns
Simply run
moon doc <symbol name or package name>to query the documentation for the corresponding symbol or package. -
moon fmtimprovements- Support formatting code blocks marked as
moonbitormoonbit testin documentation comments moon.pkg.jsonsupports configuring ignore lists
{ // in moon.pkg.json "formatter": { "ignore": [ "source1.mbt", "source2.mbt" ] } } - Support formatting code blocks marked as
-
async testnow supports limiting the maximum number of concurrently running tests, with a default value of 10, which can be modified through"max-concurrent-tests": <number>inmoon.pkg.json
Standard Library and Experimental Library Update
-
Deprecate
Container::offunctionNow
ArrayViewis the unified immutable slice that can be created fromArray,FixedArray, andReadonlyArray. Therefore, initialization functions likeofandfrom_arrayare unified asType::from_array, with the parameter changed from acceptingArraytoArrayView. It is now recommended to useType::from_arrayto create containers from array literals. -
Added
MutArrayViewas the unified mutable sliceArrayViewchanged from a mutable type to an immutable type in the previous version, but sometimes it's necessary to modify elements of the original array through a slice, soMutArrayViewwas introduced as a complement.MutArrayViewcan be created from Array and FixedArray. -
Renamed
@test.Tto@test.Testand@priority_queue.Tto@priorityqueue.PriorityQueue -
String indexing improvements
string[x]will now returnUInt16. Please migrate usingcode_unit_at -
moonbitlang/x/path experimental library improvements
Supports dynamic switching between Windows path and POSIX path processing, with Python
os.pathstyle API design. -
moonbitlang/async updates
-
moonbitlang/async experimentally supports the js backend. Currently covered features include:
-
All features unrelated to IO, including
TaskGroup, control flow constructs like@async.with_timeout, async queues, etc. -
Provides a package for JS interaction called
moonbitlang/async/js_async, supporting bidirectional conversion between MoonBit async functions and JavaScript Promises, and supporting automatic cancellation handling based on AbortSignal
-
-
Added WebSocket support, which can be imported through the
moonbitlang/async/websocketpackage -
moonbitlang/async/aqueuenow supports fixed-length async queues. When the queue is full, it supports three different behaviors: blocking the writer/overwriting the oldest element/discarding the newest element, which can be controlled by parameters when creating the queue -
The HTTP client and HTTP request API in
moonbitlang/async/httpnow support specifying HTTP CONNECT proxies. It can support HTTPS proxies with full-process encryption and proxies that require authentication -
Improved the HTTP server API, now user callback functions can process one request at a time without manually managing connections
-