Fix issue 22786 (immutable element in maxElement) by always using Rebindable.

This commit is contained in:
Mathis Beer 2023-04-18 11:08:45 +02:00 committed by Petar Kirov
parent 656ae7905e
commit b818901e63

View file

@ -1292,17 +1292,6 @@ if (isInputRange!R &&
private enum bool hasConstEmptyMember(T) = is(typeof(((const T* a) => (*a).empty)(null)) : bool);
// Rebindable doesn't work with structs
// see: https://github.com/dlang/phobos/pull/6136
private template RebindableOrUnqual(T)
{
import std.typecons : Rebindable;
static if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
alias RebindableOrUnqual = Rebindable!T;
else
alias RebindableOrUnqual = Unqual!T;
}
/**
Iterates the passed range and selects the extreme element with `less`.
If the extreme element occurs multiple time, the first occurrence will be
@ -1326,10 +1315,19 @@ in
}
do
{
import std.typecons : Rebindable;
alias Element = ElementType!Range;
RebindableOrUnqual!Element seed = r.front;
Rebindable!Element seed = r.front;
r.popFront();
return extremum!(map, selector)(r, seed);
static if (is(Rebindable!Element == T[], T))
{
return extremum!(map, selector)(r, seed);
}
else
{
return extremum!(map, selector)(r, seed.get);
}
}
private auto extremum(alias map, alias selector = "a < b", Range,
@ -1339,13 +1337,14 @@ if (isInputRange!Range && !isInfinite!Range &&
!is(CommonType!(ElementType!Range, RangeElementType) == void) &&
is(typeof(unaryFun!map(ElementType!(Range).init))))
{
import std.typecons : Rebindable;
alias mapFun = unaryFun!map;
alias selectorFun = binaryFun!selector;
alias Element = ElementType!Range;
alias CommonElement = CommonType!(Element, RangeElementType);
RebindableOrUnqual!CommonElement extremeElement = seedElement;
Rebindable!CommonElement extremeElement = seedElement;
// if we only have one statement in the loop, it can be optimized a lot better
static if (__traits(isSame, map, a => a))
@ -1406,7 +1405,15 @@ if (isInputRange!Range && !isInfinite!Range &&
}
}
}
return extremeElement;
// Rebindable is an alias to T for arrays
static if (is(typeof(extremeElement) == T[], T))
{
return extremeElement;
}
else
{
return extremeElement.get;
}
}
private auto extremum(alias selector = "a < b", Range)(Range r)
@ -1522,6 +1529,17 @@ if (isInputRange!Range && !isInfinite!Range &&
assert(arr.extremum!"a.val".val == 0);
}
// https://issues.dlang.org/show_bug.cgi?id=22786
@nogc @safe nothrow pure unittest
{
struct S
{
immutable int value;
}
assert([S(5), S(6)].extremum!"a.value" == S(5));
}
// find
/**
Finds an individual element in an $(REF_ALTTEXT input range, isInputRange, std,range,primitives).