20260112 MoonBit Monthly Update Vol.07
Version:v0.7.1
-
Added warning for unused
async. This helps clean up unnecessaryasyncannotations, improving code readability and maintainability while avoiding potential stack overflow issues.pub async fn log_debug(msg : String) -> Unit { //^^^^^ Warning (unused_async): This `async` annotation is useless. println("[DEBUG] \{msg}") } -
Default value expressions in optional arguments now can raise errors. Optional arguments can now use expressions that may
raisean error as their default values. Note that the function has to be marked as "can raise error".pub async fn log_debug( msg : String, file? : @fs.File = @fs.open("log.txt", mode=WriteOnly, append=true), ) -> Unit { file.write("[DEBUG] \{msg}\n") } -
New
#declaration_onlyAttribute. Added the#declaration_onlyattribute for functions, methods, and types. This supports spec-driven development, allowing developers to define function signatures and type declarations first and provide implementations later. When used on functions/methods, the body must be filled with....Example of a TOML parser declaration:
#declaration_only type Toml #declaration_only pub fn Toml::parse(string : String) -> Toml raise { ... } #declaration_only pub fn Toml::to_string(self : Toml) -> String { ... } -
SourceLocnow displays relative paths. The display forSourceLochas been migrated to use relative paths.///| #callsite(autofill(loc)) fn show_source_loc(loc~ : SourceLoc) -> Unit { println(loc) } ///| fn main { show_source_loc() }Running
moon run. outputs:main.mbt:9:3-9:20@username/test -
Optimized warnings for array literals. Added warnings for array literals that only undergo specific operations, suggesting
ReadOnlyArrayorFixedArrayfor better compiler optimization.pub fn f() -> Unit { let a = [1, 2, 3] ^ --- [E0065] Warning (prefer_readonly_array) ignore(a[0]) let b = [1, 2, 3] ^ --- [E0066] Warning (prefer_fixed_array) b[0] = 4 }Note: These warnings are currently disabled by default. Users must manually enable them by adding warnings
+prefer_readonly_arrayand+prefer_fixed_arrayto thewarn-listinmoon.pkg. -
Pipeline Syntax Improvement Support for the syntax
e1 |> x => { e2 + x }has been added. This allows you to simplify the originale |> then(x => e2 + x)expression. -
Support annotating for-loops with loop invariants and reasoning. For example
fn test_loop_invariant_basic() -> Unit { for i = 0; i < 10; i = i + 1 { println(i) } where { invariant: i >= 0, reasoning: "i starts at 0 and increments by 1 each iteration", } } -
The behavior of inferring
Reftype through struct literal is deprecated:let x = { val: 1 } // Previously this will infer the `Ref` type. // This behavior is deprecated and // will be removed in the future let x : Ref[_] = { val: 1 } // no problem if type is known let x = Ref::{ val: 1 } // no problem if annotated let x = Ref::new(1) // you may also use `Ref::new` // instead of struct literal
- Experimental
moon.pkgSupport. We introduced an experimentalmoon.pkgconfiguration file to replacemoon.pkg.json. It uses a syntax similar to MoonBit Object Notation, simplifying configuration while remaining easy to read.
-
Compatibility: If a
moon.pkgfile exists in a package, MoonBit will use it as the configuration. -
Migration: When the environment variable
NEW_MOON_PKG=1is set,moon fmtwill automatically migrate oldmoon.pkg.jsonfiles to the new format. -
Features: Supports comments and empty configurations. All options from
moon.pkg.jsonare compatible via theoptions(...)declaration.Example of the new syntax:
// moon.pkg // import package import { "path/to/package1", "path/to/package2" as @alias, } // import package for black box test import "test" { "path/to/test_pkg1", "path/to/test_pkg2" as @alias,r } // import package for white box test import "wbtest" { "path/to/package" as @alias, } // Compatible with all options from the original moon.pkg.json options( warnings: "-unused_value-deprecated", formatter: { ignore: ["file1.mbt", "file2.mbt"] }, // Compatible with old options using "-" in names; double quotes can be used "is-main": true, "pre-build": [ { "command": "wasmer run xx $input $output", "input": "input.mbt", "output": "output.moonpkg", } ], )
-
Improved Workflow for
moon add. Runningmoon addnow automatically executesmoon updatefirst, streamlining the dependency management process. -
The refactored
moonimplementation is now enabled by default. Users can manually switch back to the older implementation usingNEW_MOON=0. -
Support for Indirect Dependencies. Users can now use methods and
implfrom a package without explicitly importing it inmoon.pkg, provided it is an indirect dependency.// @pkgA pub(all) struct T(Int) pub fn T::f() -> Unit { ... } // @pkgB pub fn make_t() -> @pkgA.T { ... } // @pkgC fn main { let t = @pkgB.make_t() t.f() }Previously,
@pkgCmust explicitly import@pkgAin itsmoon.pkg.jsonto use the method@pkgA.T::f. With indirect dependency, importing@pkgAis no longer required. The import for a package@pkgis only necessary when it's used directly as@pkg.xxx. -
moon fmtno longer formats output fromprebuild. -
moon check --fmtnow supports detecting unformatted source files. -
When the target is
js,moon'sexecution of tests and code is no longer affected by the localpackage.json. -
The build artifacts directory
targetis moved to_build, however we generated a symlinktargetpoints to_buildin order to keep backward compatibility.
-
moonbitlang/asyncChanges:-
Windows Support: Now supports Windows (MSVC only). Most features are implemented except for symbolic links and specific filesystem permissions.
-
Recursive Directory Creation:
@fs.mkdirnow has arecursive? : Bool = falseparameter. -
Process Management: Improved
@process.runcancellation. It now attempts to notify external processes to exit gracefully before forcing termination, always waiting for the process to end before returning. -
Specific Pipe Types:
@process.read_from_processandwrite_to_processnow return specialized types (ReadFromProcess/WriteToProcess) instead of generic pipes.
-
-
The Iter type in
moonbitlang/corehas migrated from internal iterator to external iterator:-
The signature of
Iter::newhas changed.Iter::newhas previously been deprecated in https://github.com/moonbitlang/core/pull/3050 -
The external iterator type
Iteratoris merged withIter. There is only one iterator type inmoonbitlang/corenow. If you have implemented the same trait for bothIterandIterator, please remove the implementation forIterator -
The name
Iteratoris now an alias ofIterand is deprecated. Similarly, the various.iterator()methods of data structures inmoonbitlang/coreare deprecated in favor of.iter()
For most users who do not construct iterators directly, the changes above should be backward-compatible. There is one notable difference in the behavior of iterators, though: previously the
Itertype can be traversed more than once. Every traversal will recompute every element in the iterator. After migrating to external iterators,Itercan be traversed only once. Traversing an iterator more than once is an anti-pattern and should be avoided. -
-
Experimental
lexmatchEnhancements. Added support for POSIX character classes (e.g.,[:digit:]) inlexmatch, while deprecating escape sequences like\w,\d, and\s.fn main { let subject = "1234abcdef" lexmatch subject { ("[[:digit:]]+" as num, _) => println("\{num}") _ => println("no match") } }
-
Fixed issues where
.mbtifiles were not working correctly in the LSP. -
New
moon idecommand line tools. Refer to https://docs.moonbitlang.com/en/latest/toolchain/moonide/index.html for documentation.moon ide peek-def: Find definitions based on location and symbol name.
///| fn main { let value = @strconv.parse_int("123") catch { error => { println("Error parsing integer: \{error}") return } } println("Parsed integer: \{value}") }Run
moon ide peek-def -loc main.mbt:3 parse_int, we can see it outputs:Definition found at file $MOON_HOME/lib/core/strconv/int.mbt | } | | ///| | /// Parse a string in the given base (0, 2 to 36), return a Int number or an error. | /// If the `~base` argument is 0, the base will be inferred by the prefix. 140 | pub fn parse_int(str : StringView, base? : Int = 0) -> Int raise StrConvError { | ^^^^^^^^^ | let n = parse_int64(str, base~) | if n < INT_MIN.to_int64() || n > INT_MAX.to_int64() { | range_err() | } | n.to_int() | } | | // Check whether the underscores are correct. | // Underscores must appear only between digits or between a base prefix and a digit. | | ///| | fn check_underscore(str : StringView) -> Bool { | // skip the sign | let rest = match str {moon ide outline: Lists an overview/outline of a specified package.moon doc <symbol>has been migrated tomoon ide doc <symbol>.
-
Doc tests now support
mbt check. You can writetestblocks within doc comments and receive CodeLens support for running, debugging, and updating tests.






