Please enable Javascript to view the contents

[Rust Std Trait] std::marker 与 auto trait 初见

 ·  ☕ 2 分钟

前言

    在 Rust 的 std::maker 中有几个特殊的 trait,我们之前聊到的 Copy 就是其中一个,他们都是用来描述类型的内在属性,更多的是给编译器需要的额外信息。本篇作为初见会先从整体上概括知识点。

Send/Sync

    这两个 trait 主要针对并发编程的数据竞争的问题。在正常开发过程中我们时常会遇到一个问题就是区分哪些类型是具有并发安全的属性。例如实现了 Send trait 的类型表示它在不同线程之间进行 move 是安全的。而实现了 Sync trait 的类型表示在多个线程中使用 &T 是安全的。而这两个 trait 本身是由编译器自动推导的,所以我们更多看到它们是在泛型的类型约束上。真的要把一些线程不安全的类型转换成线程安全的还是得靠例如 Mutex 这些东西。

Sized

    凡是能在编译阶段就能确定大小的类型都是满足 Sized 约束的。说句人话就是其实我们开发中经常遇到的大部分都满足 Sized。有一些特殊的动态大小类型不满足 Sized,例如不定长数组。因为函数的返回值必须是确定大小的类型,动态大小类型无法直接返回,必须隐藏在指针后面,所以在直觉上很少遇到这种动态类型。

Unpin

    Rust 中默认是移动语义,但是有时我们就是不希望这种移动发生。这就需要利用到 Pin 类型。而 Unpin 约束让类型不用受到这种限制。(老实说以前没做过类似的东西,所以目前还不太理解当中存在的必要性,等以后专门做一篇关于 Pin 的文章再讲)。

auto trait

    std::marker 中的 trait 都和 Rust 语言本身有着紧密关系。虽然它们任意一个概念单独拉出来都有很多其他东西,不过他们有一个共通点:那就是他们都是编译器一次帮我们在所有能够满足的类型上面实现,个人感觉有点 Golang 自动实现 interface 的那种意思。这个能力也是 Rust 提供我们的一个 feature,作为普通用户也能使用这个能力(虽然还没 stable)。这个在 Rust 中之前叫 OIBIT,现在叫 auto trait

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#![feature(negative_impls)]
#![feature(auto_traits)]

auto trait Valid {}

struct True;
struct False;

impl !Valid for False {}

struct MaybeValid<T>(T);

fn must_be_valid<T: Valid>(_t: T) { }

fn main() {
    // works
    must_be_valid( MaybeValid(True) );
                
    // compiler error - trait bound not satisfied
    // must_be_valid( MaybeValid(False) );
}

比较有意思的是它能够通过感叹号来指定某些类型不要实现一些 trait:

1
impl !Trait for Type
分享

saberuster
作者
saberuster
一个喜欢编程和折腾的追风少年