Summary
The last of the eight overlays in this program panics. Every coordinate fits i16.
Steps to reproduce
use i_float::int::point::IntPoint;
use i_overlay::core::fill_rule::FillRule;
use i_overlay::core::overlay::Overlay;
use i_overlay::core::overlay_rule::OverlayRule;
use i_overlay::core::solver::{Solver, Strategy};
const PTS: [(i32, i32); 3] = [(0, 0), (0, 9854), (129, -23169)];
fn main() {
let c32: Vec<Vec<IntPoint<i32>>> =
vec![PTS.iter().map(|&(x, y)| IntPoint::new(x, y)).collect()];
let c16: Vec<Vec<IntPoint<i16>>> =
vec![PTS.iter().map(|&(x, y)| IntPoint::new(x as i16, y as i16)).collect()];
for (name, strategy) in [
("List", Strategy::List),
("Tree", Strategy::Tree),
("Auto", Strategy::Auto),
("Frag", Strategy::Frag),
] {
let solver = Solver { strategy, ..Default::default() };
let r = Overlay::<i32>::with_contours_custom(&c32, &[], Default::default(), solver)
.overlay(OverlayRule::Subject, FillRule::EvenOdd);
let pts: Vec<Vec<(i32, i32)>> =
r.iter().flatten().map(|c| c.iter().map(|p| (p.x, p.y)).collect()).collect();
println!("i32 engine, {}: {:?}", name, pts);
let r = Overlay::<i16>::with_contours_custom(&c16, &[], Default::default(), solver)
.overlay(OverlayRule::Subject, FillRule::EvenOdd);
let pts: Vec<Vec<(i16, i16)>> =
r.iter().flatten().map(|c| c.iter().map(|p| (p.x, p.y)).collect()).collect();
println!("i16 engine, {}: {:?}", name, pts);
}
}
Expected behavior
Strategy::Frag on the i16 engine to return the same contour as the other three strategies do, and as it does on a release build.
Actual behavior
On a debug build:
i32 engine, List: [[(0, 9854), (0, 0), (129, -23169)]]
i16 engine, List: [[(0, 9854), (0, 0), (129, -23169)]]
i32 engine, Tree: [[(0, 9854), (0, 0), (129, -23169)]]
i16 engine, Tree: [[(0, 9854), (0, 0), (129, -23169)]]
i32 engine, Auto: [[(0, 9854), (0, 0), (129, -23169)]]
i16 engine, Auto: [[(0, 9854), (0, 0), (129, -23169)]]
i32 engine, Frag: [[(0, 9854), (0, 0), (129, -23169)]]
thread 'main' panicked at src/split/grid_layout.rs:146:29:
attempt to subtract with overflow
Frag on the i32 engine and every other strategy on the i16 engine return the same contour. On a release build there is no panic and the i16 Frag overlay prints that contour too.
Environment
- iOverlay version: 8.1.0, and current
main (0022b34)
- Rust version: 1.98.0 (88d9e12ae 2026-08-18)
- OS: macOS 26.6.2, aarch64
Additional context
The reproduction also depends on i_float for IntPoint.
BTW, this bug was found using hegel. Happy to contribute the tests if you're interested.
Summary
The last of the eight overlays in this program panics. Every coordinate fits
i16.Steps to reproduce
Expected behavior
Strategy::Fragon thei16engine to return the same contour as the other three strategies do, and as it does on a release build.Actual behavior
On a debug build:
Fragon thei32engine and every other strategy on thei16engine return the same contour. On a release build there is no panic and thei16Fragoverlay prints that contour too.Environment
main(0022b34)Additional context
The reproduction also depends on
i_floatforIntPoint.BTW, this bug was found using hegel. Happy to contribute the tests if you're interested.