Never crash: algo is panic-free (Rule 9) (#56)

- apply_tiled reads the shared image for a global filter instead of
  unreachable! if it were missing.
- panorama: bundle-adjustment params come from the placed transforms via
  filter_map; the pyramid size loop and the collapse use let-else instead
  of expect.
- inpaint/pyramid: the same while-let/let-else hunks as #40, so the two
  PRs merge in either order.
- quick selection's constant broad model keeps one documented narrow
  expect (eight fixed corners always fit).
- algo denies unwrap/expect/panic/unimplemented/todo/unreachable.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas 2026-10-04 13:40:02 -04:00 committed by GitHub
parent f8f48db78a
commit 6dffa0894c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 12 additions and 4 deletions

View File

@ -16,6 +16,7 @@
//! [`apply`] runs a filter over an area, tile by tile (in parallel with
//! rayon on native targets; single-threaded on wasm).
#![forbid(unsafe_code)]
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
mod artistic;
mod artistic_fx;
@ -906,7 +907,11 @@ pub fn apply_tiled(
};
&owned
}
(None, Halo::Bounds) => unreachable!("shared image exists for global filters"),
// `shared` is always read for global filters; read the same image if it weren't.
(None, Halo::Bounds) => {
owned = Image::read(surface, bounds.union(&area));
&owned
}
};
let mut data = kernel(params, src, *t, &ctx);
if let Some(sel) = selection {

View File

@ -616,7 +616,7 @@ fn align_layout(feats: &[ImageFeatures], matches: &[PairMatch], opts: &AlignOpti
let mp = motion.n_params();
let refine_focal = projection != Projection::Plane;
let n_glob = usize::from(opts.geometric) + usize::from(refine_focal);
let mut params: Vec<f64> = movable.iter().flat_map(|&i| motion.to_params(&tf[i].expect("placed"))).collect();
let mut params: Vec<f64> = movable.iter().filter_map(|&i| tf[i].as_ref()).flat_map(|t| motion.to_params(t)).collect();
if opts.geometric {
params.push(0.0);
}
@ -1105,7 +1105,7 @@ pub fn multiband(w: usize, h: usize, imgs: &[RoiImage], weights: &[Vec<f32>], le
// Level sizes of the panorama.
let mut sizes = vec![(w, h)];
for _ in 1..levels {
let (pw, ph) = *sizes.last().expect("non-empty");
let Some(&(pw, ph)) = sizes.last() else { break };
sizes.push((pw.div_ceil(2), ph.div_ceil(2)));
}
let mut acc: Vec<Vec<f32>> = sizes.iter().map(|&(lw, lh)| vec![0.0; lw * lh * ch]).collect();
@ -1195,7 +1195,8 @@ pub fn multiband(w: usize, h: usize, imgs: &[RoiImage], weights: &[Vec<f32>], le
}
}
// Collapse.
let mut cur = acc.pop().expect("levels ≥ 1");
// `levels ≥ 1`, so there is always a coarsest level.
let Some(mut cur) = acc.pop() else { return (vec![0.0; w * h * ch], vec![0.0; w * h]) };
for l in (0..levels - 1).rev() {
let (pw, ph) = sizes[l];
let (sw, sh) = sizes[l + 1];

View File

@ -108,6 +108,8 @@ pub fn segment(img: &RgbImage, seeds: &[bool]) -> (Gmm, Gmm, Vec<bool>) {
/// A near-uniform density over the RGB cube.
pub fn broad_model() -> Gmm {
let corners: Vec<[f32; 3]> = (0..8).map(|i| [(i & 1) as f32, ((i >> 1) & 1) as f32, ((i >> 2) & 1) as f32]).collect();
// Eight fixed, distinct samples: the fit cannot fail.
#[allow(clippy::expect_used)]
Gmm::fit(&corners, 1, 0.0).expect("non-degenerate")
}