何时将特征标记为不安全,而不是将特征中的所有功能标记为不安全?

She*_*ter 10 traits rust

在代码中说同样的事情,我什么时候会选择以下任何一个例子?

unsafe trait MyCoolTrait {
    fn method(&self) -> u8;
}

trait MyCoolTrait {
    unsafe fn method(&self) -> u8;
}
Run Code Online (Sandbox Code Playgroud)

选择在内置的性状(OIBIT)RFC规定:

不安全的特征是一种实现不安全的特性,因为它代表了某种可信的断言.请注意,不安全的特性使用起来非常安全.SendShare(注:现在叫Sync)是不安全的性状的例子:实现这些特性实际上是断言,你的类型是线程安全的.

标准库中还有另一个不安全特征的例子Searcher.它说:

特征被标记为不安全,因为next()方法返回的索引需要位于大海捞针中有效的utf8边界.这使得该特征的消费者能够在没有额外的运行时检查的情况下切割干草堆.

不幸的是,这些段落都没有真正帮助我理解何时将整个特征标记为不安全而不是某些或所有方法是正确的.

我曾经问过将某个功能标记为不安全,但这看起来有所不同.

DK.*_*DK. 13

标记功能unsafe表示可以通过调用来违反内存安全性.性状是标记unsafe,以表明它是可以通过实施它违反内存安全可言.这通常是因为特征具有其他不安全代码依赖于维护的不变量,并且这些不变量不能以任何其他方式表达.

在这种情况下Searcher,方法本身应该是安全的.也就是说,用户不必担心他们是否Searcher正确使用; 接口合同说所有电话都是安全的.你无能为力会导致这些方法违反记忆安全.

但是,不安全的代码将调用a的方法Searcher,并且这种不安全的代码将依赖于给定的Searcher实现来返回有效的UTF-8代码点边界上的偏移量.如果违反了这个假设,那么不安全的代码最终可能会导致内存安全违规.

换句话说:使用Searchers 的不安全代码的正确性取决于每个单独的Searcher实现也是正确的.或者:错误地实现此特征允许安全代码引起内存安全违规是不相关的unsafe代码.

那么为什么不标记方法unsafe呢?因为它们根本不是不安全的!他们没有任何可能违反自己的记忆安全. next_match只是扫描并返回一个Option<(usize, usize)>.只有当不安全的代码假定这些usizes是被搜索字符串的有效索引时,才存在这种危险.

那么为什么不检查结果呢?因为那会慢一些.搜索代码想要快速,这意味着它希望避免冗余检查.但是这些检查不能在Searcher界面中表达...所以相反,整个特征被标记为unsafe警告任何实现它的人,在必须遵守的代码中没有陈述或强制执行的额外条件.

当你不应该违反(必要时)必须处理线程的代码的期望时,还有SendSync:实现这些.可以让你创建线程的代码是安全的,但只要SendSync唯一的类型,他们是合适的实施.