In-place sort dispatching `__lt__`; roots items since a comparison can run user code that GCs. */
(&mut self, items: &mut [Val], chunk: &SSAChunk, slots: &mut [Val])
| 171 | |
| 172 | /* In-place sort dispatching `__lt__`; roots items since a comparison can run user code that GCs. */ |
| 173 | pub(crate) fn sort_by_lt(&mut self, items: &mut [Val], chunk: &SSAChunk, slots: &mut [Val]) -> Result<(), VmErr> { |
| 174 | let snapshot = items.to_vec(); |
| 175 | let roots_base = self.temp_roots.len(); |
| 176 | for &v in &snapshot { self.temp_roots.push(v); } |
| 177 | let mut sort_err: Option<VmErr> = None; |
| 178 | let order = Self::stable_sort_indices(snapshot.len(), |a, b| { |
| 179 | if sort_err.is_some() { return core::cmp::Ordering::Equal; } |
| 180 | match self.sort_lt(snapshot[a], snapshot[b], chunk, slots) { |
| 181 | Ok(true) => core::cmp::Ordering::Less, |
| 182 | Ok(false) => match self.sort_lt(snapshot[b], snapshot[a], chunk, slots) { |
| 183 | Ok(true) => core::cmp::Ordering::Greater, |
| 184 | Ok(false) => core::cmp::Ordering::Equal, |
| 185 | Err(e) => { sort_err = Some(e); core::cmp::Ordering::Equal } |
| 186 | }, |
| 187 | Err(e) => { sort_err = Some(e); core::cmp::Ordering::Equal } |
| 188 | } |
| 189 | }); |
| 190 | self.temp_roots.truncate(roots_base); |
| 191 | if let Some(e) = sort_err { return Err(e); } |
| 192 | for (dst, &src) in order.iter().enumerate() { items[dst] = snapshot[src]; } |
| 193 | Ok(()) |
| 194 | } |
| 195 | |
| 196 | /* Stable merge sort over `0..n`; unlike `slice::sort_by` it tolerates a non-total `cmp` (NaN keys) without aborting. */ |
| 197 | fn stable_sort_indices<F>(n: usize, mut cmp: F) -> Vec<usize> |
no test coverage detected