Rust 中的“基本类型”是什么?

问题描述 投票:0回答:1

我在某个地方学到了“基本类型”这个术语(及其属性

#[fundamental]
),现在我想了解更多有关它的信息。我依稀记得这是关于在某些情况下放松连贯性规则的。我认为引用类型是非常基本的类型。

不幸的是,网络搜索并没有给我带来多大帮助。 Rust 参考文献没有提到它(据我所知)。我刚刚发现了关于创建元组基本类型的问题引入该属性的 RFC。然而,RFC 有一个关于基本类型的段落:

  • A
    #[fundamental]
    类型
    Foo
    是一种使用毯子的类型 impl over
    Foo
    是一个重大改变。如上所述,
    &
    &mut
    是 基本的。该属性将应用于
    Box
    ,使得
    Box
    在一致性方面,其行为与
    &
    &mut
    相同。

我发现这些措辞相当难以理解,感觉我需要深入了解完整的 RFC 才能理解基本类型的这一点。我希望有人能用更简单的术语解释基本类型(当然,不要简化太多)。这个问题也可以作为一个很容易找到的知识。

为了理解基本类型,我想回答这些问题(当然,除了主要的“它们是什么?”问题之外):

  • 基本类型可以比非基本类型做得更多吗?
  • 作为库作者,我可以通过将我的某些类型标记为
    #[fundamental]
    来以某种方式受益吗?
  • 核心语言或标准库中的哪些类型是基础类型?
rust
1个回答
46
投票

通常,如果库具有泛型类型

Foo<T>
,下游 crate 无法在其上实现特征,即使
T
是某种本地类型。例如,

(

crate_a
)

struct Foo<T>(pub t: T)

(

crate_b
)

use crate_a::Foo;

struct Bar;

// This causes an error
impl Clone for Foo<Bar> {
    fn clone(&self) -> Self {
        Foo(Bar)
    }
}

对于在操场上运行的具体示例(即给出错误),

use std::rc::Rc;

struct Bar;

// This causes an error
// error[E0117]: only traits defined in the current crate
// can be implemented for arbitrary types
impl Default for Rc<Bar> {
    fn default() -> Self {
        Rc::new(Bar)
    }
}

(游乐场)


这通常使包作者能够添加(一揽子)特征的实现,而不会破坏下游包。如果最初不确定类型是否应该实现特定特征,但后来发现它应该实现,那么这非常有用。例如,我们可能有某种数字类型,它最初没有实现

num-traits
的特征。这些特征可以稍后添加,无需进行重大更改。

但是,在某些情况下,库作者希望下游 crate 能够自行实现特征。这就是

#[fundamental]
属性的用武之地。当放置在类型上时,当前未为该类型实现的任何特征都不会被实现(除非进行重大更改)。因此,只要类型参数是本地的,下游 crate 就可以实现该类型的特征(有一些复杂的规则来决定哪些类型参数对此有效)。由于基本类型不会实现给定的特征,因此可以自由地实现该特征,而不会导致一致性问题。

例如,

Box<T>
被标记为
#[fundamental]
,因此以下代码(类似于上面的
Rc<T>
版本)可以工作。
Box<T>
没有实现
Default
(除非
T
实现
Default
),所以我们可以假设它将来不会实现,因为
Box<T>
是基础。请注意,为
Default
实现
Bar
会导致问题,因为那时
Box<Bar>
已经实现了
Default

struct Bar;

impl Default for Box<Bar> {
    fn default() -> Self {
        Box::new(Bar)
    }
}

(游乐场)


另一方面,特征也可以用

#[fundamental]
来标记。这对于基本类型具有双重意义。如果任何类型当前未实现基本特征,则可以假设该类型将来不会实现它(同样,除非发生重大更改)。 Rust RFC #1023 有一些关于如何在实践中使用它的解释。在代码(下面链接)中,
FnMut
用注释
so that regex can rely that `&str: !FnMut`
标记为基础。
Regex::replace
方法
允许替换为字符串或函数,如果不是这样,那么这将不起作用,因为它们会发生冲突。

理论上,如果

Add
特征被标记为基本特征(已经讨论过),那么这可以用于在尚不具有该特征的事物之间实现加法。例如,添加
[MyNumericType; 3]
(逐点),这在某些情况下可能很有用(当然,使
[T; N]
成为基础也可以实现这一点)。


原始基本类型是

&T
&mut T
(有关所有通用原始类型的演示,请参阅 here)。在标准库中,
Box<T>
Pin<T>
也被标记为基本。

标准库中的基本特征是

Sized
Fn<T>
FnMut<T>
FnOnce<T>
Generator


请注意,

#[fundamental]
属性目前不稳定。跟踪问题是 issue #29635

© www.soinside.com 2019 - 2024. All rights reserved.