Deciding whether an array was a list or a map had been done with array_keys($a) === range(0, count($a) - 1), which allocates two arrays to answer a question the engine already knows.
array_is_list([]); // true
array_is_list([1, 2, 3]); // true
array_is_list([0 => 'a', 1 => 'b']); // true
array_is_list([1 => 'a']); // false
array_is_list(['a' => 1]); // false
$a = [0 => 'a', 1 => 'b'];
unset($a[0]);
array_is_list($a); // false — the gap matters
The unset case is the whole reason this is worth having: an array that was a list and had an element removed is no longer one, and code that serialises it to JSON silently produces an object rather than an array. That is a bug that reaches an API client rather than a test. The function is O(1) in the common case because the engine tracks packed arrays internally, which no userland implementation could match.