astral-sh/ruff · error

i is bounded by INLINE_MAX_SEGMENTS

Error message

i is bounded by INLINE_MAX_SEGMENTS

What it means

SmallSegments packs up to 7 member-access segments into a single u64. try_from_slice returns None up front when segments.len() > INLINE_MAX_SEGMENTS (7), so inside the loop u32::try_from(i) with i < 7 cannot fail; .expect("i is bounded by INLINE_MAX_SEGMENTS") documents that invariant, not a user-facing condition.

Source

Thrown at crates/ty_python_core/src/member.rs:878

        }

        // Pack into inline representation
        // Store count minus 1 (since segments are never empty, range 0-6 represents 1-7 segments)
        let mut packed = (segments.len() - 1) as u64;
        let mut prev_offset = TextSize::new(0);

        for (i, segment) in segments.iter().enumerate() {
            // Compute relative offset on-the-fly
            let relative_offset = segment.offset() - prev_offset;
            if relative_offset > TextSize::from(INLINE_MAX_RELATIVE_OFFSET) {
                return None;
            }

            let kind = segment.kind() as u64;
            let relative_offset_val = u64::from(relative_offset.to_u32());
            let segment_data = (relative_offset_val << INLINE_KIND_BITS) | kind;
            let shift = INLINE_COUNT_BITS
                + (u32::try_from(i).expect("i is bounded by INLINE_MAX_SEGMENTS")
                    * INLINE_SEGMENT_BITS);
            packed |= segment_data << shift;

            prev_offset = segment.offset();
        }

        Some(Self(packed))
    }

    #[expect(
        clippy::cast_possible_truncation,
        reason = "INLINE_COUNT_MASK ensures value is at most 7"
    )]
    const fn len(self) -> usize {
        // Add 1 because we store count minus 1
        ((self.0 & INLINE_COUNT_MASK) + 1) as usize
    }

View on GitHub (pinned to fca5c7cf2c)

Solutions

  1. Keep the segments.len() > INLINE_MAX_SEGMENTS early-return consistent with the bit layout whenever the constants change
  2. If observed at runtime, capture a repro and file a ty issue - the value was produced through an unsupported path
  3. Keep unit tests covering the 6/7/8-segment boundary in pack/iterate round trips
Defensive patterns

Strategy: validation

Validate before calling

assert!(segments.len() <= INLINE_MAX_SEGMENTS); // keep paired with the packing layout

Try / catch

let packed = std::panic::catch_unwind(|| SmallSegments::try_from_slice(&segs)); // fuzz harness isolation only

Prevention

When it happens

Trigger: Only reachable if the early-return guard at the top of try_from_slice is removed or changed inconsistently with the bit layout, or a SmallSegments value is constructed bypassing try_from_slice - an internal regression, not an input-driven failure.

Common situations: Contributors editing the packing constants (INLINE_COUNT_BITS, INLINE_SEGMENT_BITS, INLINE_MAX_SEGMENTS) without keeping the guard in sync; fuzzers mutating the packed representation.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of astral-sh/ruff@fca5c7cf2c (2026-08-20). Data as JSON: /api/errors/9f5eacd324755566. Report an issue: GitHub.