深入RUST标准库内核 (三 基础Trait) 编译器内置Trait

本书github链接:inside-rust-std-library

前面章节参见:
深入RUST标准库内核(序言) - (jianshu.com)
深入RUST标准库内核(一 概述) - (jianshu.com)
深入RUST标准库内核(二 内存)—Layout/原生指针 - (jianshu.com)
深入RUST标准库内核(二 内存)—NonNull/申请及释放 - (jianshu.com)
深入RUST标准库内核(二 内存)—mem模块/MaybeUninit - (jianshu.com)

RUST的固有(intrinsic)函数库

intrinsic库函数是指由编译器内置实现的函数,一般如下特点的函数用固有函数:

  1. 与CPU架构相关性很大,必须利用汇编实现或者利用汇编才能具备最高性能的函数,
  2. 和编译器密切相关的函数,由编译器来实现最为合适。
    上面内存库章节中已经介绍了内存部分的intrinsic库函数,本节对其他部分做简略介绍

intrinsic 原子操作函数

原子操作函数主要用于多核CPU,多线程CPU时对数据的原子操作。intrinsic库中atomic_xxx及atomic_xxx_xxx类型的函数即为原子操作函数。原子操作函数主要用于并发编程中做临界保护,并且是其他临界保护机制的基础,如Mutex,RWlock等。

数学函数及位操作函数

各种整数及浮点的数学函数实现。这一部分放在intrinsic主要是因为现代CPU对浮点计算由很多支持,这些数学函数由汇编语言来实现更具备效率,那就有必要由编译器来内置实现。

intrinsic 指令优化及调试函数

断言类: assert_xxxx 类型的函数
函数栈:caller_location

小结

intrinsic函数库是从编译器层面完成跨CPU架构的一个手段,intrinsic通常被上层的库所封装。但在操作系统编程和框架编程时,仍然会不可避免的需要接触。

RUST标准库的基础Trait

RUST中直接针对泛型实现方法定义和Trait

实现方法或Trait时,可以针对泛型来实现特定的方法和Trait,并可以给泛型添加限制以描述。可以添加的泛型限制有:无限制,泛型的原生指针(可变/不可变)类型,泛型的引用(可变/不可变)类型,泛型的数组类型,泛型的切片类型,泛型的切片引用(可变/不可变)类型,泛型的元组(可变/不可变)类型,函数类型, 需实现特定的Trait限制等。
对某个具有针对泛型的类型结构体实现方法和Trait时,也可以对类型结构体的泛型做出如上所述的限制。
举例说明:

//为所有的类型实现了Borrow Trait
impl Borrow for T {
    fn borrow(&self) -> &T {
        self
    }
}
//为所有的引用类型实现Receiver Trait
impl Receiver for &T {}

//为所有可变引用类型实现Receiver Trait
impl Receiver for &mut T {}

//为所有原生不可变指针类型实现Clone Trait
impl Clone for *const T {
     fn clone(&self) -> Self {
         *self
     }
 }
//为原生可变指针类型实现Clone Trait
impl Clone for *mut T {
     fn clone(&self) -> Self {
         *self
     }
}

//为切片类型[T]实现AsRef<[T]> Trait
impl AsRef<[T]> for [T] {
    fn as_ref(&self) -> &[T] {
        self
    }
}


// 切片的方法 具体实现的摘要
// [T;N]代表数组类型,[T]代表切片类型,
// 下面是针对所有切片类型的统一方法。
impl [T] {
    pub const fn len(&self) -> usize {
        unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata }
    }

    pub const fn is_empty(&self) -> bool {
        self.len() == 0
    }
    
    //以下代码展示了RUST代码的极简洁及易理解
    pub const fn first(&self) -> Option<&T> {
        if let [first, ..] = self { Some(first) } else { None }
    }

    pub const fn split_first(&self) -> Option<(&T, &[T])> {
        if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
    }

    pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) {
        unsafe { (self.get_unchecked(..mid), self.get_unchecked(mid..)) }
    }
    ...
    ...
}

//原生指针 具体方法的实现摘要
impl *const T {
    pub const fn is_null(self) -> bool {
        (self as *const u8).guaranteed_eq(null())
    }

    /// Casts to a pointer of another type.
    pub const fn cast(self) -> *const U {
        self as _
    }

    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
        if self.is_null() { None } else { unsafe { Some(&*self) } }
    }
    ...
    ...
}

//原生数组指针 具体方法实现摘要。需要注意,原生数组指针也是原生指针,
//此处不应该再实现 *const T的同名函数。
impl *const [T] {
    pub const fn len(self) -> usize {
        metadata(self)
    }

    pub const fn as_ptr(self) -> *const T {
        self as *const T
    }
    ...
    ...
}
// 对&A实现PartialEq<&B> Trait, 如果A实现了 PartialEQ
impl PartialEq<&B> for &A
    where
        A: PartialEq,
 {
     fn eq(&self, other: &&B) -> bool {
         PartialEq::eq(*self, *other)
     }
     fn ne(&self, other: &&B) -> bool {
         PartialEq::ne(*self, *other)
     }
}

针对限制的泛型实现方法和Trait大幅的减少了代码,受限制的泛型是RUST提供的强大的泛型语法。

编译器内置Trait代码分析

分析编译器内置Trait源代码发现源代码文件中的大部分内容实际上是参考文档。
本节主要给出对参考文档理解后的一些总结

//Send Trait
pub unsafe auto trait Send {
    // empty.
}
//原生指针不支持Send Trait实现,利用"!"表示明确的对Trait的不支持
impl !Send for *const T {}
impl !Send for *mut T {}

mod impls {
    // 实现Sync的类型的类型不可变引用支持Send
    unsafe impl Send for &T {}
    // 实现Send的类型的类型可变引用支持 Send
    unsafe impl Send for &mut T {}
}

// Sync Trait
pub unsafe auto trait Sync {
    // Empty
}
//原生指针不支持Sync Trait
impl !Sync for *const T {}
impl !Sync for *mut T {}

pub trait Sized {
    // Empty.
}

//如果一个Sized的类型要强制转换为动态大小类型,那必须实现Unsize Trait
//例如 [T;N] 实现了 Unsize<[T]>
pub trait Unsize {
    // Empty.
}

//模式匹配表达式匹配时编译器需要使用的Trait,如果一个结构实现了PartialEq,该Trait会自动被实现。
//推测这个结构应该是内存按位比较
pub trait StructuralPartialEq {
    // Empty.
}

//主要用于模式匹配,如果一个结构实现了Eq, 该Trait会自动被实现。
pub trait StructuralEq {
    // Empty.
}

//Copy,略
pub trait Copy: Clone {
    // Empty.
}

//统一实现原生类型对Copy Trait的支持
mod copy_impls {

    use super::Copy;

    macro_rules! impl_copy {
        ($($t:ty)*) => {
            $(
                impl Copy for $t {}
            )*
        }
    }

    impl_copy! {
        usize u8 u16 u32 u64 u128
        isize i8 i16 i32 i64 i128
        f32 f64
        bool char
    }

    impl Copy for ! {}

    impl Copy for *const T {}

    impl Copy for *mut T {}

    impl Copy for &T {}

    //& mut T不支持Copy,以保证RUST的借用规则
}

//PhantomData被用来在类型结构体中做一个标记,标记结构体逻辑上存在但不必有实体的成员,成员类型表现在PhantomData的泛型里
//PhantomData具体阐述请参考标准库文档。 
//PhantomData是个单元结构体,单元结构体的变量名就是单元结构体的类型名。
//所以使用的时候直接使用PhantomData即可,编译器会将泛型的类型实例化信息自动带入PhantomData中
pub struct PhantomData;

你可能感兴趣的:(深入RUST标准库内核 (三 基础Trait) 编译器内置Trait)