From 7577d2d3ae8fa203604cc3b09e2ed81678163d46 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 26 May 2025 13:54:04 -0400 Subject: [PATCH] Deprecate hacky way of making structured attrs The method tested for in the previous commit is now deprecated. Co-authored-by: Eelco Dolstra --- doc/manual/rl-next/deprecate__json.md | 11 +++++++++++ src/libexpr/eval.cc | 1 + src/libexpr/include/nix/expr/eval.hh | 2 +- src/libexpr/primops.cc | 2 ++ tests/functional/structured-attrs.sh | 3 +++ 5 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 doc/manual/rl-next/deprecate__json.md diff --git a/doc/manual/rl-next/deprecate__json.md b/doc/manual/rl-next/deprecate__json.md new file mode 100644 index 000000000..7fc05832f --- /dev/null +++ b/doc/manual/rl-next/deprecate__json.md @@ -0,0 +1,11 @@ +--- +synopsis: Deprecate manually making structured attrs with `__json = ...;` +prs: [13220] +--- + +The proper way to create a derivation using [structured attrs] in the Nix language is by using `__structuredAttrs = true` with [`builtins.derivation`]. +However, by exploiting how structured attrs are implementated, it has also been possible to create them by setting the `__json` environment variable to a serialized JSON string. +This sneaky alternative method is now deprecated, and may be disallowed in future versions of Nix. + +[structured attrs]: @docroot@/language/advanced-attributes.md#adv-attr-structuredAttrs +[`builtins.derivation`]: @docroot@/language/builtins.html#builtins-derivation diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 1a067e75c..ce35901b1 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -212,6 +212,7 @@ EvalState::EvalState( , sRight(symbols.create("right")) , sWrong(symbols.create("wrong")) , sStructuredAttrs(symbols.create("__structuredAttrs")) + , sJson(symbols.create("__json")) , sAllowedReferences(symbols.create("allowedReferences")) , sAllowedRequisites(symbols.create("allowedRequisites")) , sDisallowedReferences(symbols.create("disallowedReferences")) diff --git a/src/libexpr/include/nix/expr/eval.hh b/src/libexpr/include/nix/expr/eval.hh index a4347b3e1..27294d114 100644 --- a/src/libexpr/include/nix/expr/eval.hh +++ b/src/libexpr/include/nix/expr/eval.hh @@ -213,7 +213,7 @@ public: const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue, sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls, sFile, sLine, sColumn, sFunctor, sToString, - sRight, sWrong, sStructuredAttrs, + sRight, sWrong, sStructuredAttrs, sJson, sAllowedReferences, sAllowedRequisites, sDisallowedReferences, sDisallowedRequisites, sMaxSize, sMaxClosureSize, sBuilder, sArgs, diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index f3e3e1290..01cfb3b0e 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1427,6 +1427,8 @@ static void derivationStrictInternal( else if (i->name == state.sOutputHashMode) handleHashMode(s); else if (i->name == state.sOutputs) handleOutputs(tokenizeString(s)); + else if (i->name == state.sJson) + warn("In derivation '%s': setting structured attributes via '__json' is deprecated, and may be disallowed in future versions of Nix. Set '__structuredAttrs = true' instead.", drvName); } } diff --git a/tests/functional/structured-attrs.sh b/tests/functional/structured-attrs.sh index fe9bcc0ee..465676b41 100755 --- a/tests/functional/structured-attrs.sh +++ b/tests/functional/structured-attrs.sh @@ -45,6 +45,9 @@ test "$(<<<"$jsonOut" jq '.variables.outputs.value.out' -r)" = "$(<<<"$jsonOut" hackyExpr='derivation { name = "a"; system = "foo"; builder = "/bin/sh"; __json = builtins.toJSON { a = 1; }; }' +# Check for deprecation message +expectStderr 0 nix-instantiate --expr "$hackyExpr" --eval --strict | grepQuiet "In derivation 'a': setting structured attributes via '__json' is deprecated, and may be disallowed in future versions of Nix. Set '__structuredAttrs = true' instead." + # Check it works with the expected structured attrs hacky=$(nix-instantiate --expr "$hackyExpr") nix derivation show "$hacky" | jq --exit-status '."'"$hacky"'".env.__json | fromjson | . == {"a": 1}'