Move method
基本语法
<expression> . <identifier> <[type_arguments],*> ( <arguments> )
模块中定义
模块中定义方法:当该类型是函数中的第一个参数时,编译器将自动为其类型的声明创建方法别名
module a::m {
public struct X() has copy, drop, store;
public fun foo(x: &X) { ... } // 第一个参数是结构体类型,会自动将其定义为结构体类型的方法
public fun bar(flag: bool, x: &X) { ... } // 第一个参数不是结构体类型
}
fun example(x: a::m::X) {
x.foo(); // valid
// x.bar(true); ERROR!
}
use 函数别名
use fun <function> as <type>.<method alias>;
module a::cup {
public struct Cup<T>(T) has copy, drop, store;
public fun cup_borrow<T>(c: &Cup<T>): &T {
&c.0
}
public fun cup_value<T>(c: Cup<T>): T {
let Cup(t) = c;
t
}
public fun cup_swap<T: drop>(c: &mut Cup<T>, t: T) {
c.0 = t;
}
}
module b::example {
use fun a::cup::cup_borrow as Cup.borrow; // cup_borrow 接收参数第一个是一个结构体类型参数,所以可以被定义为方法
use fun a::cup::cup_value as Cup.value; // cup_borrow 接收参数第一个是一个结构体类型参数,所以可以被定义为方法
use fun a::cup::cup_swap as Cup.set; // cup_borrow 接收参数第一个是一个结构体类型参数,所以可以被定义为方法
fun example(c: &mut Cup<u64>) {
let _ = c.borrow(); // resolves to a::cup::cup_borrow
let v = c.value(); // resolves to a::cup::cup_value
c.set(v * 2); // resolves to a::cup::cup_swap
}
}
// use fun 中的 <function> 不必是完全解析的路径,可以使用别名代替,因此上面示例中的声明可以等效地写为
use a::cup::{Self, cup_swap};
use fun cup::cup_borrow as Cup.borrow;
use fun cup::cup_value as Cup.value;
use fun cup_swap as Cup.set;
module b::example {
fun double(c: &Cup<u64>): Cup<u64> {
let v = c.value();
Cup::new(v * 2)
}
}
fun double_double(c: Cup<u64>): (Cup<u64>, Cup<u64>) {
use fun b::example::double as Cup.dub;
(c.dub(), c.dub()) // resolves to b::example::double in both calls
}
use fun 第一个参数类型
use fun 可以在任何范围内创建,但 use fun 的目标 <function> 的第一个参数必须是 <type>
第一个参数类型 非构体类型
public struct X() has copy, drop, store;
fun new(): X { X() }
fun flag(flag: bool): u8 { if (flag) 1 else 0 }
use fun new as X.new; // ERROR!
use fun flag as X.flag; // ERROR!
// Neither `new` nor `flag` has first argument of type `X` 第一个参数的类型都不是X
第一个参数类型 是构体类型
public struct X() has copy, drop, store;
public fun by_val(_: X) {}
public fun by_ref(_: &X) {}
public fun by_mut(_: &mut X) {}
// All 3 valid, in any scope
use fun by_val as X.v;
use fun by_ref as X.r;
use fun by_mut as X.m;
public use 函数别名
a::cup::Cup.borrow 是 a::cup::Cup.cup_borrow 的公共方法别名。两者都解析为 a::cup::cup_borrow 。两者都是“公共”的,因为它们可以在 a::cup 之外使用,而无需额外的 use 或 use fun 。
module a::cup {
public struct Cup<T>(T) has copy, drop, store;
// public use
public use fun cup_borrow as Cup.borrow;
public fun cup_borrow<T>(c: &Cup<T>): &T {
&c.0
}
}
module b::example {
fun example<T: drop>(c: a::cup::Cup<u64>) {
c.borrow(); // resolves to a::cup::cup_borrow
c.cup_borrow(); // resolves to a::cup::cup_borrow
}
}
别名交互
作用域
use fun 语句的作用域是其声明的范围。在范围内,使用别名的函数调用将解析为别名的函数。
也就是说:别名函数可以被覆盖
module a::m {
public struct X() has copy, drop, store;
public fun foo(_: &X) {}
public fun bar(_: &X) {}
}
module b::other {
use a::m::X;
use fun a::m::foo as X.f;
fun example(x: &X) {
x.f(); // resolves to a::m::foo
{
use fun a::m::bar as X.f; // 原文,这里错误
x.f(); // resolves to a::m::bar
};
x.f(); // still resolves to a::m::foo
{
use fun a::m::bar as X.f;
x.f(); // resolves to a::m::bar
}
}
}
自动借用
是什么
- 可变引用,可以自动借用(降级处理?),不可变引用必须显式借用
- 局部变量必须标记为 mut 以允许 &mut 借用
为什么

示例 1 无嵌套单个结构体
module a::m {
public struct X() has copy, drop;
public fun by_val(_: X) {}
public fun by_ref(_: &X) {}
public fun by_mut(_: &mut X) {}
fun example(mut x: X) {
x.by_ref(); // resolves to a::m::by_ref(&x)
x.by_mut(); // resolves to a::m::by_mut(&mut x) 局部变量必须标记为 mut 以允许 &mut 借用
}
}
示例 2 结构体为另一个结构体的字段
module a::m {
public struct X() has copy, drop;
public fun by_val(_: X) {}
public fun by_ref(_: &X) {}
public fun by_mut(_: &mut X) {}
public struct Y has drop { x: X }
fun example(mut y: Y) {
y.x.by_ref(); // resolves to a::m::by_ref(&y.x)
y.x.by_mut(); // resolves to a::m::by_mut(&mut y.x) 局部变量必须标记为 mut 以允许 &mut 借用
}
}
示例 3 没有引用
如果未借用值,则可能会移动或复制该值。
module a::m {
public struct X() has copy, drop;
public fun by_val(_: X) {}
public fun by_ref(_: &X) {}
public fun by_mut(_: &mut X) {}
public struct Y has drop { x: X }
public fun drop_y(y: Y) { y }
fun example(y: Y) {
y.x.by_val(); // copies `y.x` since `by_val` is by-value and `X` has `copy`
y.drop_y(); // moves `y` since `drop_y` is by-value and `Y` does _not_ have `copy`
}
}