suideveloper
All questions
Sui Move

What changed in the Move 2024 edition?

November 7, 2026

Move 2024 is the current edition of Sui Move. It requires let mut for mutable variables and public on struct declarations, and it replaces friend with public(package). It also adds method syntax, enums with match, macro functions, string literals, index syntax and the single-line module a::b; label. You opt in per package by setting edition = "2024" in Move.toml, and sui move migrate handles most of the mechanical changes.

Turning it on

The edition lives in the [package] section of the manifest:

TOML
[package]
name = "my_package"
edition = "2024"

2024 is the stable edition. 2024.beta and 2024.alpha give early access to features that may still change. To convert an older package, run this from the package directory:

Terminal
sui move migrate

It adds mut where needed, adds public to structs and swaps friend declarations for public(package). It also renames identifiers that collide with the new keywords. The edition is per package, so you can use 2024 features even if your dependencies don't.

Breaking changes

  • let mut: a variable must be declared mut to be reassigned or borrowed mutably. The same goes for function parameters and destructuring (let (mut x, y) = ...).
  • public struct: every struct needs a visibility modifier, and public is the only one today. Fields stay private to the module.
  • Friends are deprecated: friend and public(friend) give way to public(package), which any module in the same package can call.
  • New keywords: enum, for, match, mut and type are reserved.

New features

Move
module book::shapes;

// Module label: no braces around the module body.

public enum Shape has copy, drop {
    Circle(u64),
    Rect { w: u64, h: u64 },
}

public fun area(s: &Shape): u64 {
    match (s) {
        Shape::Circle(r) => 3 * *r * *r,
        Shape::Rect { w, h } => *w * *h,
    }
}

public fun total(shapes: &vector<Shape>): u64 {
    let mut sum = 0;
    shapes.do_ref!(|s| sum = sum + s.area()); // macro + method syntax
    sum
}
  • Method syntax: a function whose first parameter is a type from the same module can be called as value.fn(). use fun aliases add methods to other types, and public use fun exports them for your own types.
  • Enums and match: types with several variants. match must be exhaustive and also works on primitives and structs.
  • Macros: macro fun definitions expand at the call site and take lambdas. Standard library macros such as do!, map! and fold! are now the usual way to iterate (see How do loops work in Sui Move?). assert! is a regular macro, and its error code is optional.
  • Index syntax: v[0], &mut v[i], and the same on Table, Bag, VecMap and others. Custom types can opt in with #[syntax(index)].
  • String literals: "hello" becomes a String, an ascii::String or a vector<u8>, depending on the expected type. See How do strings work in Sui Move?.
  • Positional fields: public struct Pair(u64, u64), read by index (p.0). Abilities can come after the field list.
  • Abort without a code: abort and assert!(cond) with no code derive one from the module and line.
  • Clever errors: #[error] const ENotAuthorized: vector<u8> = "..."; gives an abort a readable message (see How do error codes work in Sui Move?).

extend module for adding test-only members to another module is still experimental and needs 2024.alpha.

Gotchas

  • Old tutorials that use struct Foo has key {} without public, module x::y { ... } with friend, or let x = ...; x = ...; won't compile under 2024 until they're migrated.
  • The block form module a::b { ... } still works. It's only needed to put several modules in one file.
  • Some framework functions were renamed alongside the move to methods. For example, dynamic_field::exists_ is deprecated in favor of exists. Compiler warnings point to the replacements.

Sources

More on sui move