本书github链接:inside-rust-std-library
前面章节参见:
深入RUST标准库内核(序言) - 简书 (jianshu.com)
深入RUST标准库内核(一 概述) - 简书 (jianshu.com)
深入RUST标准库内核(二 内存)—Layout/原生指针 - 简书 (jianshu.com)
深入RUST标准库内核(二 内存)—NonNull<T>/申请及释放 - 简书 (jianshu.com)
深入RUST标准库内核(二 内存)—mem模块/MaybeUninit<T> - 简书 (jianshu.com)
深入RUST标准库内核 (三 基础Trait) 编译器内置Trait - 简书 (jianshu.com)
Borrow Trait 代码分析
Borrow Trait代码定义如下:
//实现Borrow Trait的类型一般是封装结构,如智能指针Box<T>,Rc<T>, String,Cell, RefCell等,通过borrow将内部变量的引用提供给
//外部。通常的情况下,这些也都实现了Deref,AsRef等Trait把内部变量暴露出来,所以这些Trait之间有些重复。但Borrow Trait 更主要的
//场景是在RefCell等结构中提供内部可变性,这是Deref, AsRef等Trait无能为力的区域。后继分析相关类型时再给出进一步分析。
pub trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
}
pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
fn borrow_mut(&mut self) -> &mut Borrowed;
}
//每一个类型都实现了针对自身的Borrow Trait
impl<T: ?Sized> Borrow<T> for T {
#[rustc_diagnostic_item = "noop_method_borrow"]
fn borrow(&self) -> &T {
self
}
}
//每一个类型都实现了针对自身的BorrowMut Trait
impl<T: ?Sized> BorrowMut<T> for T {
fn borrow_mut(&mut self) -> &mut T {
self
}
}
//每一个类型的引用都实现了对自身的Borrow Trait
impl<T: ?Sized> Borrow<T> for &T {
fn borrow(&self) -> &T {
&**self
}
}
//每一个类型的可变引用都实现了针对自身的Borrow Trait
impl<T: ?Sized> Borrow<T> for &mut T {
fn borrow(&self) -> &T {
&**self
}
}
//每一个类型的可变引用都实现了针对自身的BorrowMut
impl<T: ?Sized> BorrowMut<T> for &mut T {
fn borrow_mut(&mut self) -> &mut T {
&mut **self
}
}
ops 运算符 Trait 代码分析
RUST中,所有的运算符号都可以重载。
一个小规则
在重载函数中,如果重载的符号出現,编译器用规定的默认操作来实现。例如:
impl const BitAnd for u8 {
type Output = u8;
//下面函数内部的 & 符号不再引发重载,是编译器的默认按位与操作。
fn bitand(self, rhs: u8) -> u8 { self & u8 }
}
数学运算符 Trait
易理解,略
位运算符 Trait
易理解,略
关系运算符Trait
代码及分析如下
//"==" "!="的实现Trait,实现该Trait的类型可以只部分相等
pub trait PartialEq<Rhs: ?Sized = Self> {
/// “==” 重载方法
fn eq(&self, other: &Rhs) -> bool;
///`!=` 重载方法
fn ne(&self, other: &Rhs) -> bool {
!self.eq(other)
}
}
/// 实现Derive属性的过程宏
pub macro PartialEq($item:item) {
/* compiler built-in */
}
//实现该Trait的类型必须完全相等
pub trait Eq: PartialEq<Self> {
fn assert_receiver_is_total_eq(&self) {}
}
/// 实现Derive属性的过程宏
pub macro Eq($item:item) {
/* compiler built-in */
}
//用于表示关系结果的结构体
#[derive(Clone, Copy, PartialEq, Debug, Hash)]
#[repr(i8)]
pub enum Ordering {
/// 小于.
Less = -1,
/// 等于.
Equal = 0,
/// 大于.
Greater = 1,
}
impl Ordering {
pub const fn is_eq(self) -> bool {
matches!(self, Equal)
}
//以下函数体实现略
pub const fn is_ne(self) -> bool
pub const fn is_lt(self) -> bool
pub const fn is_gt(self) -> bool
pub const fn is_le(self) -> bool
pub const fn is_ge(self) -> bool
//做反转操作
pub const fn reverse(self) -> Ordering {
match self {
Less => Greater,
Equal => Equal,
Greater => Less,
}
}
//用来简化代码及更好的支持函数式编程
//举例:
// let x: (i64, i64, i64) = (1, 2, 7);
// let y: (i64, i64, i64) = (1, 5, 3);
// let result = x.0.cmp(&y.0).then(x.1.cmp(&y.1)).then(x.2.cmp(&y.2));
pub const fn then(self, other: Ordering) -> Ordering {
match self {
Equal => other,
_ => self,
}
}
//用来简化代码实及支持函数式编程
pub fn then_with<F: FnOnce() -> Ordering>(self, f: F) -> Ordering {
match self {
Equal => f(),
_ => self,
}
}
}
// "<" ">" ">=" "<=" 运算符重载结构
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
// "<" 运算符重载
fn lt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Less))
}
//"<="运算符重载
fn le(&self, other: &Rhs) -> bool {
// Pattern `Some(Less | Eq)` optimizes worse than negating `None | Some(Greater)`.
!matches!(self.partial_cmp(other), None | Some(Greater))
}
//">"运算符重载
fn gt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Greater))
}
//">="运算符重载
fn ge(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Greater | Equal))
}
}
//实现Derive的过程宏
pub macro PartialOrd($item:item) {
/* compiler built-in */
}
//用输入的闭包比较函数获取两个值中大的一个
pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v2,
Ordering::Greater => v1,
}
}
//用输入的闭包比较函数获取两个值中小的一个
pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v1,
Ordering::Greater => v2,
}
}
//以下代码易理解,略
pub trait Ord: Eq + PartialOrd<Self> {
fn cmp(&self, other: &Self) -> Ordering;
fn max(self, other: Self) -> Self
where
Self: Sized,
{
max_by(self, other, Ord::cmp)
}
fn min(self, other: Self) -> Self
where
Self: Sized,
{
min_by(self, other, Ord::cmp)
}
fn clamp(self, min: Self, max: Self) -> Self
where
Self: Sized,
{
assert!(min <= max);
if self < min {
min
} else if self > max {
max
} else {
self
}
}
}
//实现Drive 属性过程宏
pub macro Ord($item:item) {
/* compiler built-in */
}
pub fn min<T: Ord>(v1: T, v2: T) -> T {
v1.min(v2)
}
pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
pub fn max<T: Ord>(v1: T, v2: T) -> T {
v1.max(v2)
}
pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
//对于实现了PartialOrd的类型实现一个Ord的反转,这是一个
//adapter的设计模式例子
pub struct Reverse<T>(pub T);
impl<T: PartialOrd> PartialOrd for Reverse<T> {
fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
other.0.partial_cmp(&self.0)
}
fn lt(&self, other: &Self) -> bool {
other.0 < self.0
}
...
...
}
impl<T: Ord> Ord for Reverse<T> {
fn cmp(&self, other: &Reverse<T>) -> Ordering {
other.0.cmp(&self.0)
}
...
}
impl<T: Clone> Clone for Reverse<T> {
fn clone(&self) -> Reverse<T> {
Reverse(self.0.clone())
}
fn clone_from(&mut self, other: &Self) {
self.0.clone_from(&other.0)
}
}
// 具体的实现宏
mod impls {
use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::hint::unreachable_unchecked;
//PartialEq在原生类型上的实现
macro_rules! partial_eq_impl {
($($t:ty)*) => ($(
impl PartialEq for $t {
fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
}
)*)
}
impl PartialEq for () {
fn eq(&self, _other: &()) -> bool {
true
}
fn ne(&self, _other: &()) -> bool {
false
}
}
partial_eq_impl! {
bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64
}
// Eq,PartialOrd, Ord在原生类型上的实现,略
...
...
impl PartialEq for ! {
fn eq(&self, _: &!) -> bool {
*self
}
}
impl Eq for ! {}
impl PartialOrd for ! {
fn partial_cmp(&self, _: &!) -> Option<Ordering> {
*self
}
}
impl Ord for ! {
fn cmp(&self, _: &!) -> Ordering {
*self
}
}
//A实现了PartialEq<B>, PartialOrd<B>后,对&A实现PartialEq<&B>, PartialOrd<&B>
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
where
A: PartialEq<B>,
{
fn eq(&self, other: &&B) -> bool {
//注意这个调用方式,此时不能用self.eq调用。
//eq方法参数为引用
PartialEq::eq(*self, *other)
}
fn ne(&self, other: &&B) -> bool {
PartialEq::ne(*self, *other)
}
}
impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A
where
A: PartialOrd<B>,
{
fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
fn lt(&self, other: &&B) -> bool {
PartialOrd::lt(*self, *other)
}
...
...
}
//如果A实现了Ord Trait, 对&A实现Ord Trait
impl<A: ?Sized> Ord for &A
where
A: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(*self, *other)
}
}
impl<A: ?Sized> Eq for &A where A: Eq {}
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &mut A
where
A: PartialEq<B>,
{
fn eq(&self, other: &&mut B) -> bool {
PartialEq::eq(*self, *other)
}
fn ne(&self, other: &&mut B) -> bool {
PartialEq::ne(*self, *other)
}
}
impl<A: ?Sized, B: ?Sized> PartialOrd<&mut B> for &mut A
where
A: PartialOrd<B>,
{
fn partial_cmp(&self, other: &&mut B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
fn lt(&self, other: &&mut B) -> bool {
PartialOrd::lt(*self, *other)
}
...
...
}
impl<A: ?Sized> Ord for &mut A
where
A: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(*self, *other)
}
}
impl<A: ?Sized> Eq for &mut A where A: Eq {}
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &A
where
A: PartialEq<B>,
{
fn eq(&self, other: &&mut B) -> bool {
PartialEq::eq(*self, *other)
}
fn ne(&self, other: &&mut B) -> bool {
PartialEq::ne(*self, *other)
}
}
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &mut A
where
A: PartialEq<B>,
{
fn eq(&self, other: &&B) -> bool {
PartialEq::eq(*self, *other)
}
fn ne(&self, other: &&B) -> bool {
PartialEq::ne(*self, *other)
}
}
}
关系运算的运算符重载相对于数学运算符重载和位运算符重载复杂一些,但其逻辑依然是比较简单的。
?运算符 Trait代码分析
?操作是RUST支持函数式编程的一个基础。不过即使不用于函数式编程,也可大幅简化代码。
当一个类型实现了Try Trait时。可对这个类型做?操作简化代码。
Try Trait也是try..catch在RUST中的一种实现方式,但从代码的表现形式上更加简化。另外,因为能够返回具体类型,这种实现方式就不仅局限于处理异常,可以扩展到其他类似的场景。
可以定义返回类型的方法,支持链式函数调用。
Try Trait定义如下:
pub trait Try: FromResidual {
/// ?操作符正常结束的返回值类型
type Output;
/// ?操作符提前返回的值类型,后继会用实例来说明
type Residual;
/// 从Self::Output返回值类型中获得原类型的值
/// 函数必须符合下面代码的原则,
/// `Try::from_output(x).branch() --> ControlFlow::Continue(x)`.
/// 例子:
/// ```
/// #![feature(try_trait_v2)]
/// use std::ops::Try;
///
/// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
/// assert_eq!(<Option<_> as Try>::from_output(4), Some(4));
/// assert_eq!(
/// <std::ops::ControlFlow<String, _> as Try>::from_output(5),
/// std::ops::ControlFlow::Continue(5),
/// );
fn from_output(output: Self::Output) -> Self;
/// branch函数会返回ControlFlow,据此决定流程继续还是提前返回
/// 例子:
/// ```p
/// #![feature(try_trait_v2)]
/// use std::ops::{ControlFlow, Try};
///
/// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
/// assert_eq!(Err::<String, _>(3).branch(), ControlFlow::Break(Err(3)));
///
/// assert_eq!(Some(3).branch(), ControlFlow::Continue(3));
/// assert_eq!(None::<String>.branch(), ControlFlow::Break(None));
///
/// assert_eq!(ControlFlow::<String, _>::Continue(3).branch(), ControlFlow::Continue(3));
/// assert_eq!(
/// ControlFlow::<_, String>::Break(3).branch(),
/// ControlFlow::Break(ControlFlow::Break(3)),
/// );
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
}
pub trait FromResidual<R = <Self as Try>::Residual> {
/// 该函数从提前返回的值中获取原始值
///
/// 此函数必须符合下面代码的原则
/// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`.
/// 例子:
/// ```
/// #![feature(try_trait_v2)]
/// use std::ops::{ControlFlow, FromResidual};
///
/// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3));
/// assert_eq!(Option::<String>::from_residual(None), None);
/// assert_eq!(
/// ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)),
/// ControlFlow::Break(5),
/// );
/// ```
fn from_residual(residual: R) -> Self;
}
Try Trait对? 操作支持的举例如下:
//不用? 操作的代码
pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
iter: impl Iterator<Item = T>,
mut accum: A,
mut f: impl FnMut(A, T) -> R,
) -> R {
for x in iter {
let cf = f(accum, x).branch();
match cf {
ControlFlow::Continue(a) => accum = a,
ControlFlow::Break(r) => return R::from_residual(r),
}
}
R::from_output(accum)
}
// 使用? 操作的代码:
fn simple_try_fold<A, T, R: Try<Output = A>>(
iter: impl Iterator<Item = T>,
mut accum: A,
mut f: impl FnMut(A, T) -> R,
) -> R {
for x in iter {
accum = f(accum, x)?;
}
R::from_output(accum)
}
由上,可推断出T?表示如下代码
match((T as Try).branch()) {
ControlFlow::Continue(a) => a,
ControlFlow::Break(r) => return (T as Try)::from_residual(r),
}
ControlFlow类型代码如下, 主要用于指示代码控制流程指示, 逻辑上可类比于continue, break 关键字 代码如下:
pub enum ControlFlow<B, C = ()> {
/// Move on to the next phase of the operation as normal.
Continue(C),
/// Exit the operation without running subsequent phases.
Break(B),
// Yes, the order of the variants doesn't match the type parameters.
// They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
// is a no-op conversion in the `Try` implementation.
}
impl<B, C> ops::Try for ControlFlow<B, C> {
type Output = C;
// convert::Infallible表示类型不会被使用,可认为是忽略类型,
//对于Residual只会用ControlFlow::Break(B), 所以用Infallible明确说明不会用到此类型
type Residual = ControlFlow<B, convert::Infallible>;
fn from_output(output: Self::Output) -> Self {
ControlFlow::Continue(output)
}
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self {
ControlFlow::Continue(c) => ControlFlow::Continue(c),
ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)),
}
}
impl<B, C> ops::FromResidual for ControlFlow<B, C> {
// Infallible表示类型不会被用到
fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
match residual {
ControlFlow::Break(b) => ControlFlow::Break(b),
}
}
}
Option的Try Trait实现:
impl<T> ops::Try for Option<T> {
type Output = T;
// Infallible是一种错误类型,但该错误永远也不会发生,这里需要返回None,
// 所以需要用Option类型,但因为只用None。所以Some使用Infallible来表示不会被使用,这也表现了RUST的安全理念,一定在类型定义的时候保证代码安全。
type Residual = Option<convert::Infallible>;
fn from_output(output: Self::Output) -> Self {
Some(output)
}
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self {
Some(v) => ControlFlow::Continue(v),
None => ControlFlow::Break(None),
}
}
}
impl<T> const ops::FromResidual for Option<T> {
#[inline]
fn from_residual(residual: Option<convert::Infallible>) -> Self {
match residual {
None => None,
}
}
}
一个Iterator::try_fold()的实现:
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
let mut accum = init;
while let Some(x) = self.next() {
accum = f(accum, x)?;
}
//try 关键字将accum转化为R类型变量
try { accum }
}
小结
利用Try Trait,程序员可以实现自定义类型的?,提供函数式编程的有力手段并简化代码,提升代码的理解度。