diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 80c2631c245..b2c5c292f45 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -35,6 +35,7 @@ mod iter; mod raw; mod rotate; mod sort; +mod specialize; #[stable(feature = "rust1", since = "1.0.0")] pub use iter::{Chunks, ChunksMut, Windows}; @@ -2866,13 +2867,7 @@ impl [T] { where T: Clone, { - if let Some((last, elems)) = self.split_last_mut() { - for el in elems { - el.clone_from(&value); - } - - *last = value - } + specialize::SpecFill::spec_fill(self, value); } /// Fills `self` with elements returned by calling a closure repeatedly. diff --git a/library/core/src/slice/specialize.rs b/library/core/src/slice/specialize.rs new file mode 100644 index 00000000000..16a9588989c --- /dev/null +++ b/library/core/src/slice/specialize.rs @@ -0,0 +1,58 @@ +use crate::ptr::write_bytes; + +pub(super) trait SpecFill { + fn spec_fill(&mut self, value: T); +} + +impl SpecFill for [T] { + default fn spec_fill(&mut self, value: T) { + if let Some((last, elems)) = self.split_last_mut() { + for el in elems { + el.clone_from(&value); + } + + *last = value + } + } +} + +impl SpecFill for [T] { + default fn spec_fill(&mut self, value: T) { + for item in self.iter_mut() { + *item = value; + } + } +} + +impl SpecFill for [u8] { + fn spec_fill(&mut self, value: u8) { + // SAFETY: this is slice of u8 + unsafe { + let ptr = self.as_mut_ptr(); + let len = self.len(); + write_bytes(ptr, value, len); + } + } +} + +impl SpecFill for [i8] { + fn spec_fill(&mut self, value: i8) { + // SAFETY: this is slice of i8 + unsafe { + let ptr = self.as_mut_ptr(); + let len = self.len(); + write_bytes(ptr, value as u8, len); + } + } +} + +impl SpecFill for [bool] { + fn spec_fill(&mut self, value: bool) { + // SAFETY: this is slice of bool + unsafe { + let ptr = self.as_mut_ptr(); + let len = self.len(); + write_bytes(ptr, value as u8, len); + } + } +}