libexpr: Soft-deprecate __overrides
Change-Id: I787e69e1dad6edc5ccdb747b74a9ccd6e8e13bb3
This commit is contained in:
parent
ac6974777e
commit
7210ed1b87
20 changed files with 86 additions and 12 deletions
|
@ -1,12 +1,16 @@
|
||||||
---
|
---
|
||||||
synopsis: Deprecated URL literals
|
synopsis: Deprecated language features
|
||||||
issues: [fj#437]
|
issues: [fj#437]
|
||||||
cls: [1736, 1735, 1744]
|
cls: [1785, 1736, 1735, 1744]
|
||||||
category: Breaking Changes
|
category: Breaking Changes
|
||||||
credits: [piegames, horrors]
|
credits: [piegames, horrors]
|
||||||
---
|
---
|
||||||
|
|
||||||
URL literals have long been obsolete and discouraged of use, and now they are officially deprecated.
|
A system for deprecation (and then the planned removal) of undesired language features has been put into place.
|
||||||
This means that all URLs must be properly put within quotes like all other strings.
|
It is controlled via feature flags much like experimental features, except that the deprecations are enabled default,
|
||||||
|
and can be disabled via the flags for backwards compatibility (opt-out with `--extra-deprecated-features` or the Nix configuration file).
|
||||||
|
|
||||||
To ease migration, they can still be enabled with `--extra-deprecated-features url-literals` for now.
|
- `url-literals`: **URL literals** have long been obsolete and discouraged of use, and now they are officially deprecated.
|
||||||
|
This means that all URLs must be properly put within quotes like all other strings.
|
||||||
|
- `rec-set-overrides`: **__overrides** is an old arcane syntax which has not been in use for more than a decade.
|
||||||
|
It is soft-deprecated with a warning only, with the plan to turn that into an error in a future release.
|
||||||
|
|
|
@ -249,6 +249,7 @@ EvalState::EvalState(
|
||||||
.findFile = symbols.create("__findFile"),
|
.findFile = symbols.create("__findFile"),
|
||||||
.nixPath = symbols.create("__nixPath"),
|
.nixPath = symbols.create("__nixPath"),
|
||||||
.body = symbols.create("body"),
|
.body = symbols.create("body"),
|
||||||
|
.overrides = symbols.create("__overrides"),
|
||||||
}
|
}
|
||||||
, repair(NoRepair)
|
, repair(NoRepair)
|
||||||
, emptyBindings(0)
|
, emptyBindings(0)
|
||||||
|
|
|
@ -48,7 +48,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct AstSymbols {
|
struct AstSymbols {
|
||||||
Symbol sub, lessThan, mul, div, or_, findFile, nixPath, body;
|
Symbol sub, lessThan, mul, div, or_, findFile, nixPath, body, overrides;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -676,6 +676,12 @@ template<> struct BuildAST<grammar::expr::ancient_let> : change_head<BindingsSta
|
||||||
|
|
||||||
template<> struct BuildAST<grammar::expr::rec_set> : change_head<BindingsState> {
|
template<> struct BuildAST<grammar::expr::rec_set> : change_head<BindingsState> {
|
||||||
static void success(const auto & in, BindingsState & b, ExprState & s, State & ps) {
|
static void success(const auto & in, BindingsState & b, ExprState & s, State & ps) {
|
||||||
|
// Before inserting new attrs, check for __override and throw an error
|
||||||
|
// (the error will initially be a warning to ease migration)
|
||||||
|
if (!featureSettings.isEnabled(Dep::RecSetOverrides) && b.attrs.attrs.contains(ps.s.overrides)) {
|
||||||
|
ps.overridesFound(ps.at(in));
|
||||||
|
}
|
||||||
|
|
||||||
b.attrs.pos = ps.at(in);
|
b.attrs.pos = ps.at(in);
|
||||||
b.attrs.recursive = true;
|
b.attrs.recursive = true;
|
||||||
s.pushExpr<ExprAttrs>(b.attrs.pos, std::move(b.attrs));
|
s.pushExpr<ExprAttrs>(b.attrs.pos, std::move(b.attrs));
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
///@file
|
///@file
|
||||||
|
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
#include "logging.hh"
|
||||||
|
|
||||||
namespace nix::parser {
|
namespace nix::parser {
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ struct State
|
||||||
|
|
||||||
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
|
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
|
||||||
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);
|
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);
|
||||||
|
void overridesFound(const PosIdx pos);
|
||||||
void addAttr(ExprAttrs * attrs, AttrPath && attrPath, std::unique_ptr<Expr> e, const PosIdx pos);
|
void addAttr(ExprAttrs * attrs, AttrPath && attrPath, std::unique_ptr<Expr> e, const PosIdx pos);
|
||||||
std::unique_ptr<Formals> validateFormals(std::unique_ptr<Formals> formals, PosIdx pos = noPos, Symbol arg = {});
|
std::unique_ptr<Formals> validateFormals(std::unique_ptr<Formals> formals, PosIdx pos = noPos, Symbol arg = {});
|
||||||
std::unique_ptr<Expr> stripIndentation(const PosIdx pos,
|
std::unique_ptr<Expr> stripIndentation(const PosIdx pos,
|
||||||
|
@ -58,6 +60,17 @@ inline void State::dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void State::overridesFound(const PosIdx pos) {
|
||||||
|
// Added 2024-09-18. Turn into an error at some point in the future.
|
||||||
|
// See the documentation on deprecated features for more details.
|
||||||
|
warn(
|
||||||
|
"%s found at %s. This feature is deprecated and will be removed in the future. Use %s to silence this warning.",
|
||||||
|
"__overrides",
|
||||||
|
positions[pos],
|
||||||
|
"--extra-deprecated-features rec-set-overrides"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
inline void State::addAttr(ExprAttrs * attrs, AttrPath && attrPath, std::unique_ptr<Expr> e, const PosIdx pos)
|
inline void State::addAttr(ExprAttrs * attrs, AttrPath && attrPath, std::unique_ptr<Expr> e, const PosIdx pos)
|
||||||
{
|
{
|
||||||
AttrPath::iterator i;
|
AttrPath::iterator i;
|
||||||
|
@ -123,6 +136,12 @@ inline void State::addAttr(ExprAttrs * attrs, AttrPath && attrPath, std::unique_
|
||||||
dupAttr(attrPath, pos, j->second.pos);
|
dupAttr(attrPath, pos, j->second.pos);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Before inserting new attrs, check for __override and throw an error
|
||||||
|
// (the error will initially be a warning to ease migration)
|
||||||
|
if (attrs->recursive && !featureSettings.isEnabled(Dep::RecSetOverrides) && i->symbol == s.overrides) {
|
||||||
|
overridesFound(pos);
|
||||||
|
}
|
||||||
|
|
||||||
// This attr path is not defined. Let's create it.
|
// This attr path is not defined. Let's create it.
|
||||||
e->setName(i->symbol);
|
e->setName(i->symbol);
|
||||||
attrs->attrs.emplace(std::piecewise_construct,
|
attrs->attrs.emplace(std::piecewise_construct,
|
||||||
|
|
|
@ -27,6 +27,15 @@ struct DeprecatedFeatureDetails
|
||||||
constexpr size_t numDepFeatures = 1 + static_cast<size_t>(Dep::UrlLiterals);
|
constexpr size_t numDepFeatures = 1 + static_cast<size_t>(Dep::UrlLiterals);
|
||||||
|
|
||||||
constexpr std::array<DeprecatedFeatureDetails, numDepFeatures> depFeatureDetails = {{
|
constexpr std::array<DeprecatedFeatureDetails, numDepFeatures> depFeatureDetails = {{
|
||||||
|
{
|
||||||
|
.tag = Dep::RecSetOverrides,
|
||||||
|
.name = "rec-set-overrides",
|
||||||
|
.description = R"(
|
||||||
|
Allow `__overrides` in recursive attribute sets.
|
||||||
|
|
||||||
|
Use fix point functions (e.g. `lib.fix` in Nixpkgs) instead.
|
||||||
|
)",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.tag = Dep::UrlLiterals,
|
.tag = Dep::UrlLiterals,
|
||||||
.name = "url-literals",
|
.name = "url-literals",
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace nix {
|
||||||
*/
|
*/
|
||||||
enum struct DeprecatedFeature
|
enum struct DeprecatedFeature
|
||||||
{
|
{
|
||||||
|
RecSetOverrides,
|
||||||
UrlLiterals,
|
UrlLiterals,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -53,10 +53,11 @@ done
|
||||||
for i in lang/parse-okay-*.nix; do
|
for i in lang/parse-okay-*.nix; do
|
||||||
echo "parsing $i (should succeed)";
|
echo "parsing $i (should succeed)";
|
||||||
i=$(basename "$i" .nix)
|
i=$(basename "$i" .nix)
|
||||||
# Hard-code that these two files are allowed to use url literals (because they test them)
|
|
||||||
if [[ "$i" == "parse-okay-url" || "$i" == "parse-okay-regression-20041027" ]]
|
if [ -e "lang/$i.flags" ]; then
|
||||||
then
|
extraArgs="$(cat "lang/$i.flags")"
|
||||||
extraArgs="--extra-deprecated-features url-literals"
|
else
|
||||||
|
extraArgs=""
|
||||||
fi
|
fi
|
||||||
if
|
if
|
||||||
expect 0 nix-instantiate --parse ${extraArgs-} - < "lang/$i.nix" \
|
expect 0 nix-instantiate --parse ${extraArgs-} - < "lang/$i.nix" \
|
||||||
|
@ -75,8 +76,14 @@ done
|
||||||
for i in lang/eval-fail-*.nix; do
|
for i in lang/eval-fail-*.nix; do
|
||||||
echo "evaluating $i (should fail)";
|
echo "evaluating $i (should fail)";
|
||||||
i=$(basename "$i" .nix)
|
i=$(basename "$i" .nix)
|
||||||
|
|
||||||
|
if [ -e "lang/$i.flags" ]; then
|
||||||
|
extraArgs="$(cat "lang/$i.flags")"
|
||||||
|
else
|
||||||
|
extraArgs=""
|
||||||
|
fi
|
||||||
if
|
if
|
||||||
expectStderr 1 nix-instantiate --eval --strict --show-trace "lang/$i.nix" \
|
expectStderr 1 nix-instantiate --eval --strict --show-trace ${extraArgs-} "lang/$i.nix" \
|
||||||
| sed "s!$(pwd)!/pwd!g" > "lang/$i.err"
|
| sed "s!$(pwd)!/pwd!g" > "lang/$i.err"
|
||||||
then
|
then
|
||||||
diffAndAccept "$i" err err.exp
|
diffAndAccept "$i" err err.exp
|
||||||
|
@ -90,8 +97,14 @@ for i in lang/eval-okay-*.nix; do
|
||||||
echo "evaluating $i (should succeed)";
|
echo "evaluating $i (should succeed)";
|
||||||
i=$(basename "$i" .nix)
|
i=$(basename "$i" .nix)
|
||||||
|
|
||||||
|
if [ -e "lang/$i.flags" ]; then
|
||||||
|
extraArgs="$(cat "lang/$i.flags")"
|
||||||
|
else
|
||||||
|
extraArgs=""
|
||||||
|
fi
|
||||||
|
|
||||||
if test -e "lang/$i.exp.xml"; then
|
if test -e "lang/$i.exp.xml"; then
|
||||||
if expect 0 nix-instantiate --eval --xml --no-location --strict \
|
if expect 0 nix-instantiate --eval --xml --no-location --strict ${extraArgs-} \
|
||||||
"lang/$i.nix" > "lang/$i.out.xml"
|
"lang/$i.nix" > "lang/$i.out.xml"
|
||||||
then
|
then
|
||||||
diffAndAccept "$i" out.xml exp.xml
|
diffAndAccept "$i" out.xml exp.xml
|
||||||
|
|
1
tests/functional/lang/eval-fail-set-override.flags
Normal file
1
tests/functional/lang/eval-fail-set-override.flags
Normal file
|
@ -0,0 +1 @@
|
||||||
|
--extra-deprecated-features rec-set-overrides
|
1
tests/functional/lang/eval-okay-attrs6.flags
Normal file
1
tests/functional/lang/eval-okay-attrs6.flags
Normal file
|
@ -0,0 +1 @@
|
||||||
|
--extra-deprecated-features rec-set-overrides
|
1
tests/functional/lang/eval-okay-inherit-from.flags
Normal file
1
tests/functional/lang/eval-okay-inherit-from.flags
Normal file
|
@ -0,0 +1 @@
|
||||||
|
--extra-deprecated-features rec-set-overrides
|
1
tests/functional/lang/eval-okay-overrides.flags
Normal file
1
tests/functional/lang/eval-okay-overrides.flags
Normal file
|
@ -0,0 +1 @@
|
||||||
|
--extra-deprecated-features rec-set-overrides
|
1
tests/functional/lang/parse-okay-rec-set-override-nowarning.exp
Symbolic link
1
tests/functional/lang/parse-okay-rec-set-override-nowarning.exp
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
parse-okay-rec-set-override-warning.exp
|
|
@ -0,0 +1 @@
|
||||||
|
--extra-deprecated-features rec-set-overrides
|
1
tests/functional/lang/parse-okay-rec-set-override-nowarning.nix
Symbolic link
1
tests/functional/lang/parse-okay-rec-set-override-nowarning.nix
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
parse-okay-rec-set-override-warning.nix
|
|
@ -0,0 +1,2 @@
|
||||||
|
warning: __overrides found at «stdin»:3:16. This feature is deprecated and will be removed in the future. Use --extra-deprecated-features rec-set-overrides to silence this warning.
|
||||||
|
warning: __overrides found at «stdin»:4:2. This feature is deprecated and will be removed in the future. Use --extra-deprecated-features rec-set-overrides to silence this warning.
|
|
@ -0,0 +1 @@
|
||||||
|
[ ({ a = rec { __overrides = { }; }; }) (rec { __overrides = { }; }) ({ __overrides = { }; }) (rec { "${("__overrides" + "")}" = { }; }) ]
|
|
@ -0,0 +1,9 @@
|
||||||
|
[
|
||||||
|
# Should warn
|
||||||
|
{ a = rec {}; a.__overrides = {}; }
|
||||||
|
rec { __overrides = {}; }
|
||||||
|
# Should not warn: Not recursive
|
||||||
|
{ __overrides = {}; }
|
||||||
|
# Should not warn: Dynamic
|
||||||
|
rec { ${"__overrides" + ""} = {}; }
|
||||||
|
]
|
|
@ -0,0 +1 @@
|
||||||
|
--extra-deprecated-features url-literals
|
1
tests/functional/lang/parse-okay-url.flags
Normal file
1
tests/functional/lang/parse-okay-url.flags
Normal file
|
@ -0,0 +1 @@
|
||||||
|
--extra-deprecated-features url-literals
|
Loading…
Reference in a new issue