From bbc7c604e76bbfa257005b514060c9547d53fe90 Mon Sep 17 00:00:00 2001 From: zseri Date: Tue, 11 Jan 2022 00:54:11 +0100 Subject: [PATCH 1/4] Discourage nested 'with' expressions --- rfcs/0120-no-nested-with.md | 90 +++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 rfcs/0120-no-nested-with.md diff --git a/rfcs/0120-no-nested-with.md b/rfcs/0120-no-nested-with.md new file mode 100644 index 000000000..6b1e40f49 --- /dev/null +++ b/rfcs/0120-no-nested-with.md @@ -0,0 +1,90 @@ +--- +feature: no-nested-with +start-date: 2021-01-11 +author: Alain Zscheile (@zseri) +co-authors: @sternenseemann +shepherd-team: (names, to be nominated and accepted by RFC steering committee) +shepherd-leader: (name to be appointed by RFC steering committee) +related-issues: (will contain links to implementation PRs) +--- + +# Summary +[summary]: #summary + +Disallow or discourage usage of multiple `with` expressions covering +the same expression / forbid nesting `with` expressions, even indirectly. +If infeasible in general (e.g. forbidding it in all nix expressions), +this can be limited to nixpkgs. + +# Motivation +[motivation]: #motivation + +It makes static analysis of nixpkgs easier, because as soon as `with` +expressions are nested, it becomes basically impossible to [statically +deduce where any free variable comes from] without implementing a +full-blown nix evaluator including lazy evaluation, which is difficult as +soon as `with` expressions and mutually recursive imports are involved +(e.g. as currently present in `nixpkgs/lib/systems/{inspect,parse}.nix`). + +With this approach, any reference to any free variable can be easily +resolved to the enclosing `with` expression "scope-include", and +because this `with` expression couldn't then be enclosed by another +one, even indirectly, no lookup ambiguity exists. + +# Detailed design +[design]: #detailed-design + +At least warn about any nested usage of `with` expressions, at least when they get evaluated, +possibly even when they get parsed. After a grace period, abort instead. + +# Examples and Interactions +[examples-and-interactions]: #examples-and-interactions + +```nix +pkgs: { + # allowed + a = with pkgs; patchelf; + + # disallowed + b = with pkgs; with lib; patchelf; + + # also disallowed + c = with pkgs; { + meta = with lib; { + license = with licenses; [ mit ]; + }; + }; +} +``` + +# Drawbacks +[drawbacks]: #drawbacks + +* It makes it necessary to modify some parts of nixpkgs. + +# Alternatives +[alternatives]: #alternatives + +* Introduce a kind of `with-only` expression which allows bringing an attrset + into scope while simultaneously hiding the outer scope, such that all + inner free variables are either resolved via the given attrset, or + result in an error. + +* Completely ban the usage of `with` in nixpkgs (this would probably result in + too much churn, which seems excessive for this problem). + +# Unresolved questions +[unresolved]: #unresolved-questions + +Decide if this is enough. + +e.g. +* Mutually recursive imports combined with `with` expressions also make static + analysis harder, because they require lazyness at the level of scope lookups, + which is difficult to implement corrently. +* Check if any use case is too much negatively impacted by this. + +# Future work +[future]: #future-work + +Unknown. From afed5f53e3118441c454a6ef0ab2d65afd43db6e Mon Sep 17 00:00:00 2001 From: zseri Date: Fri, 14 Jan 2022 15:15:41 +0100 Subject: [PATCH 2/4] 0120: add link to 0110 --- rfcs/0120-no-nested-with.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rfcs/0120-no-nested-with.md b/rfcs/0120-no-nested-with.md index 6b1e40f49..2acc3f23c 100644 --- a/rfcs/0120-no-nested-with.md +++ b/rfcs/0120-no-nested-with.md @@ -69,6 +69,10 @@ pkgs: { into scope while simultaneously hiding the outer scope, such that all inner free variables are either resolved via the given attrset, or result in an error. + Similar to this is [RFC 110](https://github.com/NixOS/rfcs/pull/110), + which introduces an `inherit-as-list` construct which solves the primary + application of `with-only`, list specification in `meta` attributes of + nixpkgs derivatons. * Completely ban the usage of `with` in nixpkgs (this would probably result in too much churn, which seems excessive for this problem). From 7d04c475c2e69fe7e9afcf5e431cd504564c6fbf Mon Sep 17 00:00:00 2001 From: zseri Date: Fri, 14 Jan 2022 15:21:40 +0100 Subject: [PATCH 3/4] 0120: amend future work section --- rfcs/0120-no-nested-with.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0120-no-nested-with.md b/rfcs/0120-no-nested-with.md index 2acc3f23c..84e89f0c3 100644 --- a/rfcs/0120-no-nested-with.md +++ b/rfcs/0120-no-nested-with.md @@ -91,4 +91,4 @@ e.g. # Future work [future]: #future-work -Unknown. +* Static analyzers and transpilers for Nix From 927add21f62ca8bbe8a5aa6c06659670ce18db8b Mon Sep 17 00:00:00 2001 From: zseri Date: Mon, 11 Apr 2022 10:59:36 +0200 Subject: [PATCH 4/4] 0120: refine multiple sections --- rfcs/0120-no-nested-with.md | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/rfcs/0120-no-nested-with.md b/rfcs/0120-no-nested-with.md index 84e89f0c3..a9371531f 100644 --- a/rfcs/0120-no-nested-with.md +++ b/rfcs/0120-no-nested-with.md @@ -26,16 +26,20 @@ full-blown nix evaluator including lazy evaluation, which is difficult as soon as `with` expressions and mutually recursive imports are involved (e.g. as currently present in `nixpkgs/lib/systems/{inspect,parse}.nix`). -With this approach, any reference to any free variable can be easily -resolved to the enclosing `with` expression "scope-include", and -because this `with` expression couldn't then be enclosed by another -one, even indirectly, no lookup ambiguity exists. - # Detailed design [design]: #detailed-design -At least warn about any nested usage of `with` expressions, at least when they get evaluated, -possibly even when they get parsed. After a grace period, abort instead. +At least warn about any nested usage of `with` expressions, +at least when they get evaluated, possibly even when they get parsed. +After a grace period ("real time", probably a few months or years, not as in +"a timeout when interpreting" because that wouldn't make sense), +abort instead. + +When the full approach (aborting instead of warning) is applied, +any reference to any free variable can be easily resolved +to the enclosing `with` expression "scope-include", and because +this `with` expression couldn't then be enclosed by another +one, even indirectly, no lookup ambiguity exists. # Examples and Interactions [examples-and-interactions]: #examples-and-interactions @@ -60,7 +64,7 @@ pkgs: { # Drawbacks [drawbacks]: #drawbacks -* It makes it necessary to modify some parts of nixpkgs. +* Backward-incompatible, requires changing Nix code used "in the wild". # Alternatives [alternatives]: #alternatives @@ -74,8 +78,8 @@ pkgs: { application of `with-only`, list specification in `meta` attributes of nixpkgs derivatons. -* Completely ban the usage of `with` in nixpkgs (this would probably result in - too much churn, which seems excessive for this problem). +* Completely ban the usage of `with` in nixpkgs; + seems unnecessarily excessive for this problem. # Unresolved questions [unresolved]: #unresolved-questions @@ -85,7 +89,7 @@ Decide if this is enough. e.g. * Mutually recursive imports combined with `with` expressions also make static analysis harder, because they require lazyness at the level of scope lookups, - which is difficult to implement corrently. + which is difficult to implement corrently. e.g. [nix2js#2](https://github.com/YZITE/nix2js/issues/2) * Check if any use case is too much negatively impacted by this. # Future work