Skip to content

Commit

Permalink
Fix Bugzilla issue 24342: Actually check that range and sentinel type…
Browse files Browse the repository at this point in the history
…s match in `until` before using "sentinel as subrange" mode.

`until` does special magic when `Sentinel` consists of multiple elements of `Range`. However, because `Range` can be a range of ranges, in which case even a `Sentinel` that is a range may still only be a single element, we must confirm that the element type of `Sentinel` is actually the same as `Range` before enabling this.
The `immutable ElementEncodingType` idiom is stolen from `startsWith`, which forms the basis of `until` anyways (see `predSatisfied`).
  • Loading branch information
FeepingCreature authored and thewilsonator committed Jan 18, 2024
1 parent 4b8a3e9 commit 5976fe8
Showing 1 changed file with 12 additions and 2 deletions.
14 changes: 12 additions & 2 deletions std/algorithm/searching.d
Original file line number Diff line number Diff line change
Expand Up @@ -5053,7 +5053,8 @@ if (isInputRange!Range)
_input = input;
_sentinel = sentinel;
_openRight = openRight;
static if (isInputRange!Sentinel)
static if (isInputRange!Sentinel
&& is(immutable ElementEncodingType!Sentinel == immutable ElementEncodingType!Range))
{
_matchStarted = predSatisfied();
_done = _input.empty || _sentinel.empty || openRight && _matchStarted;
Expand Down Expand Up @@ -5120,7 +5121,8 @@ if (isInputRange!Range)
assert(!empty, "Can not popFront of an empty Until");
if (!_openRight)
{
static if (isInputRange!Sentinel)
static if (isInputRange!Sentinel
&& is(immutable ElementEncodingType!Sentinel == immutable ElementEncodingType!Range))
{
_input.popFront();
_done = _input.empty || _sentinel.empty;
Expand Down Expand Up @@ -5237,6 +5239,7 @@ pure @safe unittest
assert(equal(r.save, "foo"));
}
}

// https://issues.dlang.org/show_bug.cgi?id=14543
pure @safe unittest
{
Expand Down Expand Up @@ -5267,3 +5270,10 @@ pure @safe unittest
assert("one two three".until!((a,b)=>a.toUpper == b)("TWO", No.openRight).equal("one two"));
}

// https://issues.dlang.org/show_bug.cgi?id=24342
pure @safe unittest
{
import std.algorithm.comparison : equal;
assert(["A", "BC", "D"].until("BC", No.openRight).equal(["A", "BC"]));
assert([[1], [2, 3], [4]].until([2, 3], No.openRight).equal([[1], [2, 3]]));
}

0 comments on commit 5976fe8

Please sign in to comment.