Skip to content

tf_split crashes on splits at domain boundaries / single-split inputs #251

Description

@fabian-s

R/split-combine.R:34-39. After stripping a split equal to tf_domain(x)[1], splits may be numeric(0), and if (splits[length(splits)] == tf_domain(x)[2]) becomes if (logical(0)) → "argument is of length zero". Separately, include = "left" indexes end[1:(length(end) - 1)], which breaks when length(end) == 1.

Reproduce

library(tf)
x <- tf_rgp(2)
tf_split(x, splits = 0)               # arg of length zero
tf_split(x, splits = tf_domain(x))    # also breaks
tf_split(x, splits = 0.5, include = "left")  # single split, include = "left"

Fix

Guard the empty-splits case (return x wrapped in a length-1 list, or error explicitly). Use seq_len(length(end) - 1) instead of 1:(length(end) - 1). Document the include offset behavior — it's currently a multiple of get_resolution() (a heuristic power of ten) and can drop or keep grid points unexpectedly on fine grids.

Regression test

test_that("tf_split handles boundary and single-split inputs", {
  x <- tf_rgp(2)
  expect_no_error(tf_split(x, splits = 0))
  expect_no_error(tf_split(x, splits = tf_domain(x)))
  expect_no_error(tf_split(x, splits = 0.5, include = "left"))
  expect_no_error(tf_split(x, splits = 0.5, include = "right"))
})

Found in the June-2026 ground-up review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions