This extends the `error: cannot coerce a TYPE to a string` message to print the value that could not be coerced. This helps with debugging by making it easier to track down where the value is being produced from, especially in errors with deep or unhelpful stack traces.
4 KiB
String interpolation
String interpolation is a language feature where a string, path, or attribute name can contain expressions enclosed in ${ }
(dollar-sign with curly brackets).
Such a construct is called interpolated string, and the expression inside is an interpolated expression.
Examples
String
Rather than writing
"--with-freetype2-library=" + freetype + "/lib"
(where freetype
is a [derivation]), you can instead write
"--with-freetype2-library=${freetype}/lib"
The latter is automatically translated to the former.
A more complicated example (from the Nix expression for Qt):
configureFlags = "
-system-zlib -system-libpng -system-libjpeg
${if openglSupport then "-dlopen-opengl
-L${mesa}/lib -I${mesa}/include
-L${libXmu}/lib -I${libXmu}/include" else ""}
${if threadSupport then "-thread" else "-no-thread"}
";
Note that Nix expressions and strings can be arbitrarily nested;
in this case the outer string contains various interpolated expressions that themselves contain strings (e.g., "-thread"
), some of which in turn contain interpolated expressions (e.g., ${mesa}
).
Path
Rather than writing
./. + "/" + foo + "-" + bar + ".nix"
or
./. + "/${foo}-${bar}.nix"
you can instead write
./${foo}-${bar}.nix
Attribute name
Attribute names can be interpolated strings.
Example
let name = "foo"; in { ${name} = 123; }
{ foo = 123; }
Attributes can be selected with interpolated strings.
Example
let name = "foo"; in { foo = 123; }.${name}
123
Interpolated expression
An expression that is interpolated must evaluate to one of the following:
-
a string
-
a path
-
an attribute set that has a
__toString
attribute or anoutPath
attribute__toString
must be a function that takes the attribute set itself and returns a stringoutPath
must be a string
This includes derivations or flake inputs (experimental).
A string interpolates to itself.
A path in an interpolated expression is first copied into the Nix store, and the resulting string is the store path of the newly created store object.
Example
$ mkdir foo
Reference the empty directory in an interpolated expression:
"${./foo}"
"/nix/store/2hhl2nz5v0khbn06ys82nrk99aa1xxdw-foo"
A derivation interpolates to the store path of its first output.
Example
let pkgs = import <nixpkgs> {}; in "${pkgs.hello}"
"/nix/store/4xpfqf29z4m8vbhrqcz064wfmb46w5r7-hello-2.12.1"
An attribute set interpolates to the return value of the function in the __toString
applied to the attribute set itself.
Example
let a = { value = 1; __toString = self: toString (self.value + 1); }; in "${a}"
"2"
An attribute set also interpolates to the value of its outPath
attribute.
Example
let a = { outPath = "foo"; }; in "${a}"
"foo"
If both __toString
and outPath
are present in an attribute set, __toString
takes precedence.
Example
let a = { __toString = _: "yes"; outPath = throw "no"; }; in "${a}"
"yes"
If neither is present, an error is thrown.
Example
let a = {}; in "${a}"
error: cannot coerce a set to a string: { } at «string»:4:2: 3| in 4| "${a}" | ^