mirror of
https://github.com/NixOS/nix.git
synced 2025-11-20 09:19:36 +01:00
Fix the caching of float and ints
Because of a dirty limit of the `std::visit(overloaded` trick, these were silently casted to booleans
This commit is contained in:
parent
531cc6593a
commit
5d058d81f1
3 changed files with 33 additions and 24 deletions
|
|
@ -1135,7 +1135,7 @@ tree_cache::AttrValue cachedValueFor(const Value& v)
|
||||||
valueToCache = tree_cache::unknown_t{};
|
valueToCache = tree_cache::unknown_t{};
|
||||||
break;
|
break;
|
||||||
case nBool:
|
case nBool:
|
||||||
valueToCache = v.boolean;
|
valueToCache = tree_cache::wrapped_basetype<bool>{v.boolean};
|
||||||
break;
|
break;
|
||||||
case nString:
|
case nString:
|
||||||
valueToCache = tree_cache::string_t{
|
valueToCache = tree_cache::string_t{
|
||||||
|
|
@ -1153,10 +1153,10 @@ tree_cache::AttrValue cachedValueFor(const Value& v)
|
||||||
valueToCache = tree_cache::attributeSet_t{};
|
valueToCache = tree_cache::attributeSet_t{};
|
||||||
break;
|
break;
|
||||||
case nInt:
|
case nInt:
|
||||||
valueToCache = v.integer;
|
valueToCache = tree_cache::wrapped_basetype<int64_t>{v.integer};
|
||||||
break;
|
break;
|
||||||
case nFloat:
|
case nFloat:
|
||||||
valueToCache = v.fpoint;
|
valueToCache = tree_cache::wrapped_basetype<double>{v.fpoint};
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
return valueToCache;
|
return valueToCache;
|
||||||
|
|
@ -1249,8 +1249,16 @@ ValueCache::CacheResult ValueCache::getValue(Store & store, const std::vector<Sy
|
||||||
mkString(dest, s.first, context);
|
mkString(dest, s.first, context);
|
||||||
return ValueCache::CacheResult{CacheHit};
|
return ValueCache::CacheResult{CacheHit};
|
||||||
},
|
},
|
||||||
[&](bool b) {
|
[&](tree_cache::wrapped_basetype<bool> b) {
|
||||||
dest.mkBool(b);
|
dest.mkBool(b.value);
|
||||||
|
return ValueCache::CacheResult{CacheHit};
|
||||||
|
},
|
||||||
|
[&](tree_cache::wrapped_basetype<int64_t> i) {
|
||||||
|
dest.mkInt(i.value);
|
||||||
|
return ValueCache::CacheResult{CacheHit};
|
||||||
|
},
|
||||||
|
[&](tree_cache::wrapped_basetype<double> d) {
|
||||||
|
dest.mkFloat(d.value);
|
||||||
return ValueCache::CacheResult{CacheHit};
|
return ValueCache::CacheResult{CacheHit};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -118,13 +118,6 @@ struct AttrDb
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
AttrId setBool(
|
|
||||||
AttrKey key,
|
|
||||||
bool b)
|
|
||||||
{
|
|
||||||
return addEntry(key, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<AttrId> getId(const AttrKey& key)
|
std::optional<AttrId> getId(const AttrKey& key)
|
||||||
{
|
{
|
||||||
auto state(_state->lock());
|
auto state(_state->lock());
|
||||||
|
|
@ -180,11 +173,11 @@ struct AttrDb
|
||||||
return {{rowId, string_t{queryAttribute.getStr(2), context}}};
|
return {{rowId, string_t{queryAttribute.getStr(2), context}}};
|
||||||
}
|
}
|
||||||
case AttrType::Bool:
|
case AttrType::Bool:
|
||||||
return {{rowId, queryAttribute.getInt(2) != 0}};
|
return {{rowId, wrapped_basetype<bool>{queryAttribute.getInt(2) != 0}}};
|
||||||
case AttrType::Int:
|
case AttrType::Int:
|
||||||
return {{rowId, queryAttribute.getInt(2)}};
|
return {{rowId, wrapped_basetype<int64_t>{queryAttribute.getInt(2)}}};
|
||||||
case AttrType::Double:
|
case AttrType::Double:
|
||||||
return {{rowId, queryAttribute.getInt(2)}};
|
return {{rowId, wrapped_basetype<double>{(double)queryAttribute.getInt(2)}}};
|
||||||
case AttrType::Unknown:
|
case AttrType::Unknown:
|
||||||
return {{rowId, unknown_t{}}};
|
return {{rowId, unknown_t{}}};
|
||||||
case AttrType::Thunk:
|
case AttrType::Thunk:
|
||||||
|
|
@ -359,17 +352,17 @@ const RawValue RawValue::fromVariant(const AttrValue & value)
|
||||||
res.value = x.first;
|
res.value = x.first;
|
||||||
res.context = x.second;
|
res.context = x.second;
|
||||||
},
|
},
|
||||||
[&](bool x) {
|
[&](wrapped_basetype<bool> x) {
|
||||||
res.type = AttrType::Bool;
|
res.type = AttrType::Bool;
|
||||||
res.value = x ? "1" : "0";
|
res.value = x.value ? "1" : "0";
|
||||||
},
|
},
|
||||||
[&](int64_t x) {
|
[&](wrapped_basetype<int64_t> x) {
|
||||||
res.type = AttrType::Int;
|
res.type = AttrType::Int;
|
||||||
res.value = std::to_string(x);
|
res.value = std::to_string(x.value);
|
||||||
},
|
},
|
||||||
[&](double x) {
|
[&](wrapped_basetype<double> x) {
|
||||||
res.type = AttrType::Double;
|
res.type = AttrType::Double;
|
||||||
res.value = std::to_string(x);
|
res.value = std::to_string(x.value);
|
||||||
},
|
},
|
||||||
[&](unknown_t x) { res.type = AttrType::Unknown; },
|
[&](unknown_t x) { res.type = AttrType::Unknown; },
|
||||||
[&](missing_t x) { res.type = AttrType::Missing; },
|
[&](missing_t x) { res.type = AttrType::Missing; },
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,14 @@ struct unknown_t {};
|
||||||
struct thunk_t {};
|
struct thunk_t {};
|
||||||
struct failed_t { string error; };
|
struct failed_t { string error; };
|
||||||
struct missing_t { Symbol attrName; };
|
struct missing_t { Symbol attrName; };
|
||||||
|
|
||||||
|
// Putting several different primitive types in an `std::variant` partially
|
||||||
|
// breaks the `std::visit(overloaded{...` hackery because of the implicit cast
|
||||||
|
// from one to another which breaks the exhaustiveness check.
|
||||||
|
// So we wrap them in a trivial class just to force the disambiguation
|
||||||
|
template<typename T>
|
||||||
|
struct wrapped_basetype{ T value; };
|
||||||
|
|
||||||
typedef uint64_t AttrId;
|
typedef uint64_t AttrId;
|
||||||
|
|
||||||
typedef std::pair<AttrId, Symbol> AttrKey;
|
typedef std::pair<AttrId, Symbol> AttrKey;
|
||||||
|
|
@ -82,9 +90,9 @@ typedef std::variant<
|
||||||
thunk_t,
|
thunk_t,
|
||||||
missing_t,
|
missing_t,
|
||||||
failed_t,
|
failed_t,
|
||||||
bool,
|
wrapped_basetype<bool>,
|
||||||
int64_t,
|
wrapped_basetype<int64_t>,
|
||||||
double
|
wrapped_basetype<double>
|
||||||
> AttrValue;
|
> AttrValue;
|
||||||
|
|
||||||
struct RawValue {
|
struct RawValue {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue