1
Fork 0
mirror of https://github.com/RGBCube/Site synced 2025-07-30 12:37:50 +00:00

blog(nix-iceberg): even more text

This commit is contained in:
RGBCube 2025-06-05 18:42:50 +03:00
parent 3abff9ebd1
commit 104140528a
Signed by: RGBCube
SSH key fingerprint: SHA256:CzqbPcfwt+GxFYNnFVCqoN5Itn4YFrshg1TrnACpA5M
2 changed files with 198 additions and 24 deletions

View file

@ -171,7 +171,7 @@ html, body {
@apply wrap-anywhere;
}
&:not(:has(> code:only-child)) {
&:not(:has(> code:only-child)):not(:has(> img)) {
@apply px-1;
&:not(.font-mono) {
@ -230,8 +230,8 @@ html, body {
code:not(pre > code) {
@apply border-1 border-dotted px-2 py-0.5 border-black dark:border-white;
a:hover &:not(:is(h1, h2, h3, h4, h5, h6) *),
a:active &:not(:is(h1, h2, h3, h4, h5, h6) *) {
a:hover &:not(:only-child, :is(h1, h2, h3, h4, h5, h6) *),
a:active &:not(:only-child, :is(h1, h2, h3, h4, h5, h6) *) {
@apply border-transparent;
}
}
@ -252,9 +252,7 @@ html, body {
}
& li::before {
@apply pr-1;
content: "[" counter(item) "]";
content: counter(item) ". ";
}
}

View file

@ -15,12 +15,10 @@ it a reputation of being arcane and hard to use.
I'll be explaining the contents of the following iceberg chart, which includes
some truly arcane examples of Nix code.
Some knowledge of Nix is required, you may get confused in the terminology if
you've never used it.
Some knowledge of Nix is required, you may get confused with the terminology if
you've never used Nix.
![The Nix Iceberg](/assets/images/nix-iceberg.webp)
[Here's the original source for this image, on cohost.](https://cohost.org/leftpaddotpy/post/3885451-the-nix-iceberg)
[![The Nix Iceberg](/assets/images/nix-iceberg.webp)](https://cohost.org/leftpaddotpy/post/3885451-the-nix-iceberg)
Let's start:
@ -53,7 +51,7 @@ So, what are we doing in this snippet?
2. Creating a derivation that runs an echo command, which writes a Nix
expression to the output file.
3. Then we import the output file, forcing the derivation to be realized as we
accessed the contents of it.
just accessed the contents of it.
> Wait, what does _realization_ mean?
@ -518,14 +516,14 @@ known.
# Tier 3: `assigned nix hacker at employment`
<h2>
<h2><small>
```sh
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p python3
```
</h2>
</small></h2>
_(taken verbatim from `man nix-shell`)_
@ -564,7 +562,16 @@ print t
## `--accept-flake-config` more like `--pwn-me-mommy`
TODO
The
[`accept-flake-config`](https://nix.dev/manual/nix/2.29/command-ref/conf-file#conf-accept-flake-config)
Nix configuration variable or `--accept-flake-config` flag in Nix commands
allows Nix to unconditionally accept flake `nixConfig`'s.
This is dangerous, because this can enable `builtins.importNative` by enabling
the
[`allow-unsafe-native-code-during-evaluation`](https://nix.dev/manual/nix/2.29/command-ref/conf-file#conf-allow-unsafe-native-code-during-evaluation)
option, which then allows Nix expresions to load arbitrary dynamic libraries,
which can do anything as they are not confined to the Nix evaluation sandbox.
## Zilch
@ -716,8 +723,7 @@ But if two attribute sets that are compared have the same memory location, Nix
ignores this and does a pointer comparison, totally ignoring all members. This
is a hack.
[Link to code that does this.](https://github.com/NixOS/nix/blob/aa165301d1ae3b306319a6a834dc1d4e340a7112/src/libexpr/eval.cc#L2525-L2528)
Here's the snippet:
[Here's the snippet:](https://github.com/NixOS/nix/blob/aa165301d1ae3b306319a6a834dc1d4e340a7112/src/libexpr/eval.cc#L2525-L2528)
```cpp
bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx)
@ -778,10 +784,11 @@ impure binaries to the Nix store.
## `rec { a = 5; b = a + 1; __overrides.a = 6; }`
There is a special field named `__overrides` in recursive attrset expressions,
which simply overrides the parent attribute set with the keys inside it. This is
different from the update operator (`//`) because that will not override the
self-references in the recursive attribute set.
There is a special field named `__overrides` in keyed expressions (attribute
sets, `let-in`'s and as secret third thing), which simply overrides the parent
attribute set with the keys inside it. This is different from the update
operator (`//`) because that will not override the self-references in the
recursive attribute set.
`rec { a = 5; b = a + 1; __overrides.a = 6; }.b` will evaluate to 7, while
`(rec { a = 5; b = a + 1; } // { a = 6; }).b` will evaluate to 6.
@ -813,7 +820,58 @@ TODO
## `let a = _: -1; or = 6; in [ a or 9 ]`
TODO
The Nix parser is weird.
Normally, `or` is used for attribute path selection defaults:
```nix
{ foo = 123; }.not-here.not-here-either or 123
```
That above evaluates to `123`.
But when parsing an expression that is not an attribute-select, `or` is treated
as an identifier. This means that in the following `let-in`, we are passing `or`
to `a`.
```nix
let
a = _: -1;
or = 6;
in a or
```
But there is another piece of weirdness. Function applications that use the
literal `or` have higher precedence than the spaces when parsing lists, so these
two codeblocks are not equivalent:
```nix
let
a = _: -1;
or = 6;
in [ a or ]
```
> This evaluates to `[ -1 ]`
```nix
let
a = _: -1;
foo = 6;
in [ a foo ]
```
> This evaluates to `[ <LAMBDA> 6 ]`
However, this behaviour might get removed in the future. But currently, in the
Nix version that I am using which is `2.28.3`, it prints this warning instead:
```text
warning: at «string»:4:6: This expression uses `or` as an identifier in a way that will change in a future Nix release.
Wrap this entire expression in parentheses to preserve its current meaning:
(a or)
Give feedback at https://github.com/NixOS/nix/pull/11121
```
## eelco's home address is in nixpkgs
@ -821,16 +879,25 @@ TODO
## `restrict-eval`
TODO
[From the Nix manual:](https://nix.dev/manual/nix/2.29/command-ref/conf-file.html?highlight=restrict-eval#conf-restrict-eval)
> If set to true, the Nix evaluator will not allow access to any files outside
> of `builtins.nixPath`, or to URIs outside of `allowed-uris`.
## nix2
## `__noChroot`
TODO
When the
[`sandbox`](https://nix.dev/manual/nix/2.29/command-ref/conf-file.html?highlight=__nos#conf-sandbox)
Nix configuration value is set to `relaxed`, fixed-output derivations (FODs)
that have the `__noChroot` attribute set to `true` will not run in the Nix
sandbox.
## cloud scale hydra
TODO
## `(_:_) != (_:_)` but `(a:a) == (a:a)`
Evaluating `(_:_) == (_:_)`, we see that it is `false`, which means the two
@ -854,3 +921,112 @@ TODO
This is the legacy `let` syntax. Equivalent to `let huh = "?"; in huh`.
## Tier 6: `has meowed before`
### `let { body = 1; __overrides.body = 2; }`
This is a combination of [`__override`](#rec-a-5-b-a-1-overridesa-6-) for keyed
experessions and the [`legacy let syntax`](#let-huh-body-huh-).
### function identity is load bearing on importing nixpkgs
Since
[attribute sets with function members compare function identities (memory locations)](#let-f-a-a-s-ff-in-f-f-s-s),
comparing any attribute set that contains a function is load-bearing on the
function's identity.
The way this affects importing nixpkgs is that nixpkgs internally compares
stdenvs, which contain functions, to determine whether if we are
cross-compiling.nixpkgs internally compares stdenvs, which contain functions, to
determine whether if we are cross-compiling.
Therefore, function identity really **is** load bearing on importing nixpkgs.
### `import <nix/fetchurl.nix>`
This looks like we are importing <nix>, and getting the `fetchurl.nix` file in
it.
Let's see if that is true:
```nix
nix-repl> builtins.readDir <nix>
```
<!-- TODO: Say: There doesn't seem to be a `fetchurl.nix` file here. After it doesn't exist. -->
This is because `<nix>` is actually `corepkgs`, which is a Nix path
[defined inside Nix itself.](https://github.com/NixOS/nix/blob/2afc84fddf463b22196aeb70587bc0c9259e330f/src/libexpr/eval.cc#L321)
[Later, the `fetchurl.nix` path is defined in `corepkgs`](https://github.com/NixOS/nix/blob/2afc84fddf463b22196aeb70587bc0c9259e330f/src/libexpr/eval.cc#L363)
and its contents are set to a
[generated C++ header.](https://github.com/NixOS/nix/blob/2afc84fddf463b22196aeb70587bc0c9259e330f/src/libexpr/meson.build#L129-L135)
### test suite of nix wasn't run
TODO
### fixed-output derivation sandboxing
TODO
### `importNative`
[`builtins.importNative`](https://nix.dev/manual/nix/2.24/command-ref/conf-file.html#conf-allow-unsafe-native-code-during-evaluation)
allows Nix expressions to import arbitrary dynamic libraries to produce Nix
expressions.
Of course, this is turned off by default as it is a security risk. You probably
shouldn't use this.
### `chromium recompressTarball`
TODO
### more than 1 million chars of indents breaks things
The weird Nix parser
[hard codes `1000000`](https://github.com/NixOS/nix/blob/2afc84fddf463b22196aeb70587bc0c9259e330f/src/libexpr/include/nix/expr/parser-state.hh#L250)
instead of `SIZE_MAX` when determining the minimum indent to strip in strings
spanning multiple lines.
So when you have a line with more than a million spaces for the indent, it is
ignored and not included in the minimum indent calculation.
## Tier 7: `wears animal ears to NixCon`
<h2><small>
```nix
nix-repl> builtins.fromJSON ''{"uwu\u0000": 1, "uwu": 2}''
{ uwu = 2; "uwu" = 1; }
```
</small></h2>
TODO
## `(_: builtins.break _)`
TODO
## multiplayer tic-tac-toe in nix repl
TODO
## `let e="e"; in [001.2e01e.30.4]`
TODO
## `/__corepkgs__/`
[Already explained previously.](#import-nixfetchurlnix)
## `some-expr`
TODO
## `__darwinAllowLocalNetworking`
TODO
## `builtins.derivationStrict`