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

Luk*_*odt 29 rust

在某个地方,我选择了“基本类型”(及其基本属性#[fundamental])一词,而现在我想了解更多有关它的信息。我隐约记得它是关于在某些情况下放宽一致性规则的。而且我认为引用类型就是这种基本类型。

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

  • 一种#[fundamental]类型Foo是在其中实施全面实施Foo是一项重大变化。如上所述,&并且&mut是基本的。将此属性应用于Box,使其Box 行为与相干性相同&&mut相对于相干性。

我觉得这句话很难理解,感觉到我需要对整个RFC有深入的了解才能了解基本类型的这一点。我希望有人可以用更简单的术语来解释基本类型(当然,不必过多简化)。这个问题也可以作为一条容易找到的知识。

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

  • 基本类型能比非基本类型做更多的事情吗?
  • 作为图书馆作者,我可以从某些类型上标记为#[fundamental]吗?
  • 核心语言或标准库中的哪些类型是基本的?

SCa*_*lla 29

通常,如果库具有泛型类型Foo<T>,则下游板条箱无法在其上实现特征,即使T是某些本地类型也是如此。例如,

crate_a

struct Foo<T>(pub t: T)
Run Code Online (Sandbox Code Playgroud)

crate_b

use crate_a::Foo;

struct Bar;

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

对于在操场上工作的具体示例(即出现错误),

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

(操场)


通常,这可以使板条箱创建者添加(完全)性状实现,而不会破坏下游板条箱。在最初不确定某个类型应实现特定特征的情况下,这很好,但后来变得很清楚,它应该实现。例如,我们可能有某种数字类型,最初并未实现from的特征num-traits。这些特征可以稍后添加,而无需进行重大更改。

但是,在某些情况下,图书馆作者希望下游的板条箱能够自己实现特征。这就是#[fundamental]属性的来源。当放置在一个类型上时,当前未为此类型实现的任何特征都不会实现(除非有重大更改)。结果,只要类型参数是本地的,下游的板条箱就可以实现该类型的特征(有一些复杂的规则来确定为此使用哪种类型参数)。由于基本类型不会实现给定的特征,因此可以自由实现该特征而不会引起一致性问题。

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

struct Bar;

impl Default for Box<Bar> {
    fn default() -> Self {
        Box::new(Bar)
    }
}
Run Code Online (Sandbox Code Playgroud)

(操场)


另一方面,特征也可以用标记#[fundamental]。这对于基本类型具有双重含义。如果当前没有任何类型实现基本特征,则可以假定该类型将来不会实现(再次,除非做出重大更改)。我不确定在实践中如何使用它。在代码(下面链接)中,FnMut已标记为基本,并指出正则表达式需要它(关于&str: !FnMut)。我找不到它在regex板条箱中的使用位置,或者是否在其他地方使用。

从理论上讲,如果将Add特征标记为基本特征(已经讨论过),则可以将其用于在尚不具备此特征的事物之间实现加法运算。例如,添加[MyNumericType; 3](逐点),这在某些情况下可能是有用的(当然,做[T; N]基础也可以这样做)。


基本基本类型是&T&mut T(有关所有一般基本类型的说明,请参见此处)。在标准库中,Box<T>Pin<T>被标记为基本。

在标准库的基本特征是SizedFn<T>FnMut<T>FnOnce<T>Generator


请注意,该#[fundamental]属性当前不稳定。跟踪问题为问题#29635

  • 很好的答案!关于原始类型:只有少数通用原始类型:`&amp;T`、`&amp;mut T`、`*const T`、`*mut T`、`[T; N]`、`[T]`、`fn` 指针和元组。并且[全部测试](https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=9457ce9fba4a1de04b837e961201c65e)(如果这段代码没有意义,请告诉我)**看来引用是仅基本原始类型**。有趣的。我有兴趣知道为什么其他人不这样做的原因,尤其是原始指针。但我想这不是这个问题的范围。 (2认同)