1
1
Fork 0
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:
regnat 2021-02-16 18:38:27 +01:00
parent 531cc6593a
commit 5d058d81f1
3 changed files with 33 additions and 24 deletions

View file

@ -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};
}, },
}, },

View file

@ -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; },

View file

@ -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 {