Skip to content

Strategy::Frag panics with a subtract overflow on the i16 engine #88

Description

@DRMacIver

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions