概要: Rust libstd内では既に特殊化が使用されているので、特定の条件を満たすことでより効率なコードが生成される。
PartialEq<[T]>
- 最適化される処理: スライスの比較処理
- 間接的に最適化される処理:
Vec<T>,str,Stringの比較など
- 間接的に最適化される処理:
- 条件: 内部トレイト
BytewiseEqualityが実装されている場合。具体的には要素型がu8,i8,u16,i16,u32,i32,u64,i64,usize,isize,char,boolの場合 - 理由:
memcmpで効率的に比較できるため。 - ディスパッチ用トレイト: 内部トレイト
SlicePartialEq
Vec<T>::from_iter, Vec<T>::extend (ムーブ)
- 最適化される処理:
TのイテレータからのVec<T>の生成と延長- 間接的に最適化される処理:
iter.collect::<Vec<_>>()など
- 間接的に最適化される処理:
- 条件1: unstableかつunsafeなトレイト
TrustedLenが実装されている場合。これはsize_hintが正確な長さを与えることをunsafeレベルで保証するトレイトである。 (ExactSizeIteratorはsafeであり、契約の内容も微妙に異なる)[T],Option<T>,Result<T, E>由来のイテレータとstr.bytes(),iter::empty(),iter::once(),(n..m),(n..=m)はTrustedLenである。rev(),cloned(),chain(),zip(),map(),enumerate()はTrustedLenを保つ。
- 理由1: 通常の生成/延長処理では、容量を気にしながら適宜再確保をする必要があるが、イテレータの長さが判明している場合は、最初に再確保したあとはループの各ステップでは容量チェックを省略できるから。
- 条件2: イテレータが
vec.into_iter()自体だった場合 - 理由2: 当該イテレータが一度も消費されていない場合、単にもとの
vecを復元するだけでよいから。 - ディスパッチ用トレイト: 内部トレイト
SpecExtend
Vec<T>::from_iter, Vec<T>::extend (参照)
- 最適化される処理:
&TのイテレータからのVec<T>の延長 (T: Copyのとき可能) - 条件: スライスの
slice.iter()に由来するとき - 理由:
memcpyで効率よくコピー可能で、再確保も高々1回でよく、パニックガードが要らないから。 - ディスパッチ用トレイト: 内部トレイト
SpecExtend(上と同じ)
BinaryHeap<T>::extend, LinkedList<T>::extend
- 最適化される処理: イテレータからの
BinaryHeap<T>の延長とLinkedList<T>の延長- 間接的に最適化される処理:
iter.collect::<LinkedList<_>>()など
- 間接的に最適化される処理:
- 条件1:
BinaryHeap<T>をBinaryHeap<T>で延長する場合 - 理由1: swapして逆向きに追加したほうが速い場合や、ヒープの再ビルドをしたほうが速い場合がある。
- 条件2:
LinkedList<T>をLinkedList<T>で延長する場合 - 理由2: 単に連結すればよい。
- ディスパッチ用トレイト: 内部トレイト
SpecExtend
vec![x; n]
- 最適化される処理:
vec - 条件1: 要素型が
u8 - 理由1:
memsetで効率的に塗れるため。 - 条件2: 要素型が
u8,i8,u16,i16,u32,i32,u64,i64,u128,i128,usize,isize,f32,f64で値が0のとき - 理由2:
memsetで効率的に塗れるため。 - ディスパッチ用トレイト: 内部トレイト
SpecFromElem
ToString
- 最適化される処理:
to_stringによる文字列化 (一般にはDisplayに対して実装される) - 条件:
str,Cow<'a, str>,Stringのいずれかの場合 - 理由: 文字列をコピーするだけだから。
- ディスパッチ用トレイト: なし (
ToStringを直接特殊化)
iter.zip
- 最適化される処理:
iter.zip()で得られるイテレータの実装 - 条件: 内部トレイト
TrustedRandomAccessが実装されている場合。これは名前の通りインデックスを引数としてアクセスする処理を実装し、それが本来のイテレータの動作と一致することを保証する。ただし、実際にランダムアクセスのために使われることはない。slice.iter(),slice.iter_mut(),str.bytes()はTrustedRandomAccessである。cloned(),zip(),map(),enumerate(),fuse()はTrustedRandomAccessを保つ。
- 理由: この特殊化により、
slice1.iter().zip(slice2.iter())のような場合に単一のインデックス変数でループするコードが生成され、効率が良くなるらしい。 - ディスパッチ用トレイト: 内部トレイト
ZipImpl
iter.fuse
- 最適化される処理:
iter.fuse()で得られるイテレータの実装 - 条件: unstableなトレイト
FusedIteratorが実装されている場合。つまり、元のイテレータが既に、「Noneを出力したら以降はずっとNone」という性質を満たしているとき。 - 理由: 既にfusedなので、
self.doneフラグをチェックする必要がなくなる。 - ディスパッチ用トレイト: なし (
Iterator,DoubleEndedIteratorを直接特殊化)
Arc<[T]>::from, Rc<[T]>::from
- 最適化される処理:
&[T]からArc<[T]>,Rc<[T]>を作る処理 (一般にはT: Cloneなら使える) - 条件:
T: Copyのとき - 理由:
memcpyで効率的に複製できるし、cloneと違ってpanicしないのでパニックガードが要らない。 - ディスパッチ用トレイト:
ArcFromSlice,RcFromSlice