Move 2024版本迁移

Move 2024提供了新功能,包括方法语法、位置字段和循环标签。

Move 2024版本迁移

Move 2024版本迁移引入了一些变化,使得编写Move更加容易,希望也更容易阅读。源语言中相对较少的重大变化更好地使Move能够处理未来的进展。

这其中的许多变化增强了源语言,影响了编译器,而不需要对发布在链上的二进制表示进行任何更改。

现有的代码将继续编译,即使增加了这些新功能。由于这些功能是可选的,即使您的依赖项不包含它们,您也可以在您的packages中使用新功能进行编写。然而,在当前模块中选择利用新功能引入了一些重大变化。

阅读我们在Github上的迁移指南以获取完整的详细信息。

如何迁移

要将项目迁移到Move 2024 Beta版本,您有两个选项:

  1. 删除现有的 Move.lock 文件(如果存在),以确保您使用最新的 sui-framework 版本。
  2. 运行 sui move migrate 。有关更多信息,请参阅迁移指南中的 自动迁移 部分。
    1. 或者,更新您的 Move.toml 文件中的 [package] 条目,将 edition = "2024.beta"包含在内。如果这样做,您可能会收到一些新错误,作为我们的 重大变化.

自动迁移 

Move 2024包含一个自动迁移脚本,您可以在Move项目的根目录中调用 sui move migrate 来使用。运行该脚本时,您的控制台会提示您选择要使用的Move版本。如果您选择 2024.beta,脚本将调用编译器,并尝试自动更新您的代码,以避免更新引入的 重大变化 (包括将结构标记为 public、使用 mut 关键字标记可变变量、避免受限制的关键字、将 friends for public(package),甚至在许多情况下更新路径为全局路径)。

在运行此脚本后,您的控制台会显示脚本打算进行的更改的差异。如果您接受更改,脚本将自动更新您的代码和 Move.toml 文件。您现在正在使用Move 2024 Beta。

新功能

以下是Move 2024中一些新功能的简要概述。

方法语法Method syntax

现在您可以使用 . 语法将某些函数作为方法调用。例如,以下调用:

vector::push_back(&mut v, coin::value(&c));

现在可以写成:

v.push_back(c.value());

在这个例子中,如果需要,方法的接收者(vc )会自动借用(分别为 &mut v&c )。

如果函数在与接收者类型相同的模块中定义,您可以将其作为方法调用,前提是它将接收者作为其第一个参数。

对于在模块外定义的函数,您可以使用 public use funuse fun.

索引语法Index syntax

使用方法语法,您可以将某些函数注释为 #[syntax(index)] 方法。然后,您可以使用 v[i]形式的调用来调用这些方法。

例如:

*&mut v[i] = v[j];

可以解析为:

*vector::borrow_mut(&mut v, i) = *vector::borrow(&v, j);

public(package)

friend 声明以及相关的 public(friend) 可见性修饰符已经过时。取而代之的是 public(package) 可见性修饰符,它只允许在定义它们的同一包中调用函数。

位置字段Positional fields

现在您可以定义具有位置字段的结构,通过以零为基的索引来访问这些字段。例如:

public struct Pair(u64, u64) 具有复制、删除和存储功能;

然后访问每个字段:

public fun sum(p: &Pair): u64 {
  p.0 + p.1
}

正如这个例子所示,您现在可以在结构字段列表之后声明能力。

嵌套use和标准库默认值

现在您可以为了更简洁性而嵌套 使用 别名。

use sui::{balance, coin::{Self, Coin}};

此外,以下use声明现在会自动包含在每个模块中:

use std::vector;
use std::option::{Self, Option};
use sui::object::{Self, ID, UID};
use sui::transfer;
use sui::tx_context::{Self, TxContext};

相等性自动引用

相等性操作, ==!=,现在如果一侧是引用而另一侧不是,则会自动借用。例如:

fun check(x: u64, r: &u64): bool {
  x == r
}

相当于:

fun check(x: u64, r: &u64): bool {
  &x == r
}

这种自动借用可以发生在 ==!=.

循环标签

当嵌套循环时,直接跳转到外层循环可能更方便。例如:

let mut i = 0;
let mut j = 0;
let mut terminate_loop = false;
while (i < 10) {
    while (j < 10) {
        if (haystack(i, j) == needle) {
            terminate_loop = true;
            break;
        };
        j = j + 1;
    };
    if (terminate_loop) break;
    i = i + 1;
}

现在,您可以直接为外部循环(在本例中为outer )命名,并一次性中断它:

let mut i = 0;
let mut j = 0;
'outer: while (i < 10) {
    while (j < 10) {
        if (haystack(i, j) == needle) break'outer;
        j = j + 1;
    };
    i = i + 1;
}

break (带值的)

现在可以从循环中断中返回值。例如:

let mut i = 0;
let x: u64 = loop {
    if (v[i] > 10) break i;
    i = i + 1;
};

您也可以使用标签来实现这一点。例如:

let mut i = 0;
let mut j = 0;
let item = 'outer: loop {
    while (j < 10) {
        let item = haystack(i, j);
        if (item == needle) break'outer option::some(item);
        j = j + 1;
    };
    i = i + 1;
    if (i == 10) break option::none();
};

重大变更 

遗憾的是,Move 2024 中的重大变更正在增加。我们预计这些变更对现有代码的侵入性将最小化,并提供了迁移脚本,以在大多数情况下自动处理这些变更。此外,这些变更为 Move 2024 中即将推出的新功能铺平了道路。

数据类型可见性要求

目前,在Move中,所有结构体都是公共的:任何其他模块或包都可以导入它们,并按类型引用它们。为了使这一点更清晰,Move 2024要求所有结构体都必须使用public关键字声明。例如:

// legacy code
struct S { x: u64 }

// Move 2024 code
public struct S { x: u64 }

现在,任何非公共结构体都会在此时产生错误,而Move团队正在为未来的发布工作中探索新的可见性选项。

可变性要求

以前,在Move中,所有变量都是隐式可变的。例如:

fun f(s: S, y: u64): u64 {
    let a = 0;
    let S { x } = s;
    a = 1;
    x = 10;
    y = 5;
    x + y
}

现在,您必须明确声明可变变量:

fun f(s: S, mut y: u64): u64 {
    let mut a = 0;
    let S { mut x } = 5;
    a = 1;
    x = 10;
    y = 5;
    x + y
}

如果尝试在没有此明确声明的情况下重新分配或借用可变变量,则编译器将产生错误。

移除friends和 public(friend)

在Move的早期开发中引入了friends和 public(friend) 可见性,甚至早于包系统。如 public(package) 部分所示, public(package) 在Move 2024中取代了 public(friend)

下面的声明现在会产生错误:

module pkg::m {
    friend pkg::a;
    public(friend) fun f() { ... }
}

module pkg::a {
    fun calls_f() { ... pkg::m::f() ... }
}

而如果想要使函数仅在包内可见,应该写成:

module pkg::m {
    public(package) fun f() { ... }
}

module pkg::a {
    // this now works directly
    fun calls_f() { ... pkg::m::f() ... }
}

新关键字

展望未来,Move 2024 Beta为语言添加了以下关键字: enum, for, match, muttype。不幸的是,如果在其他位置发现这些关键字,编译器现在会产生解析错误。随着语言的成熟,这是必要的变更。如果执行自动迁移,迁移工具将这些重命名为 enum 等,并重写代码以使用这些转义形式。

修订的路径和命名空间

与传统的Move相比,Move 2024对路径和命名空间的工作方式进行了修订,以便未来更轻松地处理 enum 别名。考虑以下来自 sui_system 库中测试注释的代码片段:

使用sui_system::sui_system;

...

#[expected_failure(abort_code =sui_system::validator_set::EInvalidCap)]

传统的Move总是将三部分名称视为地址(sui_system)、模块(validator_set)和模块成员(EInvalidCap)。而Move 2024尊重 使用的范围,因此属性中的 sui_system 解析为模块,在整体上产生名称解析错误。

为避免这种情况是预期行为的情况,Move 2024引入了全局资格的前缀操作。要使用它,可以将此注释重写为:

use sui_system::sui_system; ... #[expected_failure(abort_code = ::sui_system::validator_set::EInvalidCap)]                              // ^ note `::` here

迁移脚本尝试在可能的情况下使用全局资格来纠正命名错误。

一直前进

Move 2024 Beta版本除了上述的重大变更外,还带来了一些强大的新功能。未来还将有更多的功能。请加入Sui邮件订阅以了解今年即将推出的 Move 新功能,包括语法宏、带模式匹配的枚举和其他用户定义的语法扩展。

请通过GitHubDiscordSui开发者论坛提供任何反馈或报告您遇到的问题。