Describe the bug
I discovered this while looking at this expression in nixpkgs:
if isAttrs licenses && licenses ? "licenseType" then
!(lib.licenses.isFree licenses)
else if isAttrs licenses then
# ...
I was curious if the first isAttrs was even necessary here. The logic of ? is defined here:
|
void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) |
|
{ |
|
Value vTmp; |
|
Value * vAttrs = &vTmp; |
|
|
|
e->eval(state, env, vTmp); |
|
|
|
for (auto & i : attrPath) { |
|
state.forceValue(*vAttrs, getPos()); |
|
const Attr * j; |
|
auto name = getName(i, state, env); |
|
if (vAttrs->type() == nAttrs && (j = vAttrs->attrs()->get(name))) { |
|
vAttrs = j->value; |
|
} else { |
|
v.mkBool(false); |
|
return; |
|
} |
|
} |
|
|
|
v.mkBool(true); |
|
} |
As you can see, no typechecks are performed. If
vAttrs isn't an attribute set, it just falls back to returning false. (Also, it seems to perform this typecheck on every attribute while iterating, rather than just once - I'd hope the compiler would catch that, but who knows, maybe that's a free performance win).
On the other hand, hasAttr forces its argument to be an attrset:
|
static void prim_hasAttr(EvalState & state, const PosIdx pos, Value ** args, Value & v) |
|
{ |
|
auto attr = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hasAttr"); |
|
state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.hasAttr"); |
|
v.mkBool(args[1]->attrs()->get(state.symbols.create(attr))); |
|
} |
Steps To Reproduce
- Enter
nix repl
- Observe that
null ? example passes fine, while hasAttr "example" null throws an error
Expected behavior
Since the documentation describes hasAttr as "a dynamic version of the ? operator", it'd be nice if their behavior was aligned, or at least documented.
Metadata
❯ nix-env --version
warning: unknown setting 'repl-overlays'
nix-env (Nix) 2.34.6
Additional context
Checklist
Add 👍 to issues you find important.
Describe the bug
I discovered this while looking at this expression in nixpkgs:
I was curious if the first
isAttrswas even necessary here. The logic of?is defined here:nix/src/libexpr/eval.cc
Lines 1501 to 1521 in b744171
As you can see, no typechecks are performed. If
vAttrsisn't an attribute set, it just falls back to returning false. (Also, it seems to perform this typecheck on every attribute while iterating, rather than just once - I'd hope the compiler would catch that, but who knows, maybe that's a free performance win).On the other hand,
hasAttrforces its argument to be an attrset:nix/src/libexpr/primops.cc
Lines 3218 to 3223 in b744171
Steps To Reproduce
nix replnull ? examplepasses fine, whilehasAttr "example" nullthrows an errorExpected behavior
Since the documentation describes hasAttr as "a dynamic version of the
?operator", it'd be nice if their behavior was aligned, or at least documented.Metadata
❯ nix-env --version
warning: unknown setting 'repl-overlays'
nix-env (Nix) 2.34.6
Additional context
Checklist
Add 👍 to issues you find important.