Mark Value pointers in Value::elems as const

This catches modification of finalized values (e.g. in prim_sort).
This commit is contained in:
Eelco Dolstra 2024-03-15 18:22:39 +01:00
parent fecff520d7
commit 3e6730ee62
4 changed files with 7 additions and 6 deletions

View File

@ -1946,7 +1946,7 @@ void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v)
} }
void EvalState::concatLists(Value & v, size_t nrLists, Value * * lists, const PosIdx pos, std::string_view errorCtx) void EvalState::concatLists(Value & v, size_t nrLists, Value * const * lists, const PosIdx pos, std::string_view errorCtx)
{ {
nrListConcats++; nrListConcats++;

View File

@ -671,7 +671,7 @@ public:
const SingleDerivedPath & p, const SingleDerivedPath & p,
Value & v); Value & v);
void concatLists(Value & v, size_t nrLists, Value * * lists, const PosIdx pos, std::string_view errorCtx); void concatLists(Value & v, size_t nrLists, Value * const * lists, const PosIdx pos, std::string_view errorCtx);
/** /**
* Print statistics, if enabled. * Print statistics, if enabled.

View File

@ -3372,7 +3372,6 @@ static void prim_sort(EvalState & state, const PosIdx pos, Value * * args, Value
auto list = state.buildList(len); auto list = state.buildList(len);
for (const auto & [n, v] : enumerate(list)) for (const auto & [n, v] : enumerate(list))
state.forceValue(*(v = args[1]->listElems()[n]), pos); state.forceValue(*(v = args[1]->listElems()[n]), pos);
v.mkList(list);
auto comparator = [&](Value * a, Value * b) { auto comparator = [&](Value * a, Value * b) {
/* Optimization: if the comparator is lessThan, bypass /* Optimization: if the comparator is lessThan, bypass
@ -3391,7 +3390,9 @@ static void prim_sort(EvalState & state, const PosIdx pos, Value * * args, Value
/* FIXME: std::sort can segfault if the comparator is not a strict /* FIXME: std::sort can segfault if the comparator is not a strict
weak ordering. What to do? std::stable_sort() seems more weak ordering. What to do? std::stable_sort() seems more
resilient, but no guarantees... */ resilient, but no guarantees... */
std::stable_sort(v.listElems(), v.listElems() + len, comparator); std::stable_sort(list.begin(), list.end(), comparator);
v.mkList(list);
} }
static RegisterPrimOp primop_sort({ static RegisterPrimOp primop_sort({

View File

@ -246,7 +246,7 @@ public:
Bindings * attrs; Bindings * attrs;
struct { struct {
size_t size; size_t size;
Value * * elems; Value * const * elems;
} bigList; } bigList;
Value * smallList[2]; Value * smallList[2];
ClosureThunk thunk; ClosureThunk thunk;
@ -425,7 +425,7 @@ public:
return internalType == tList1 || internalType == tList2 || internalType == tListN; return internalType == tList1 || internalType == tList2 || internalType == tListN;
} }
Value * * listElems() Value * const * listElems()
{ {
return internalType == tList1 || internalType == tList2 ? smallList : bigList.elems; return internalType == tList1 || internalType == tList2 ? smallList : bigList.elems;
} }