Skip to content

Commit 7f22668

Browse files
committed
Discourage nested 'with' expressions
1 parent 25c3f52 commit 7f22668

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

rfcs/0120-no-nested-with.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
---
2+
feature: no-nested-with
3+
start-date: 2021-01-11
4+
author: Ellen Emilia Anna Zscheile (@fogti)
5+
co-authors: @sternenseemann
6+
shepherd-team: (names, to be nominated and accepted by RFC steering committee)
7+
shepherd-leader: (name to be appointed by RFC steering committee)
8+
related-issues: (will contain links to implementation PRs)
9+
---
10+
11+
# Summary
12+
[summary]: #summary
13+
14+
Disallow or discourage usage of multiple `with` expressions covering
15+
the same expression / forbid nesting `with` expressions, even indirectly.
16+
If infeasible in general (e.g. forbidding it in all nix expressions),
17+
this can be limited to nixpkgs.
18+
19+
# Motivation
20+
[motivation]: #motivation
21+
22+
It makes static analysis of nixpkgs easier, because as soon as `with`
23+
expressions are nested, it becomes basically impossible to [statically
24+
deduce where any free variable comes from] without implementing a
25+
full-blown nix evaluator including lazy evaluation, which is difficult as
26+
soon as `with` expressions and mutually recursive imports are involved
27+
(e.g. as currently present in `nixpkgs/lib/systems/{inspect,parse}.nix`).
28+
29+
# Detailed design
30+
[design]: #detailed-design
31+
32+
At least warn about any nested usage of `with` expressions,
33+
at least when they get evaluated, possibly even when they get parsed.
34+
After a grace period ("real time", probably a few months or years, not as in
35+
"a timeout when interpreting" because that wouldn't make sense),
36+
abort instead.
37+
38+
When the full approach (aborting instead of warning) is applied,
39+
any reference to any free variable can be easily resolved
40+
to the enclosing `with` expression "scope-include", and because
41+
this `with` expression couldn't then be enclosed by another
42+
one, even indirectly, no lookup ambiguity exists.
43+
44+
# Examples and Interactions
45+
[examples-and-interactions]: #examples-and-interactions
46+
47+
```nix
48+
pkgs: {
49+
# allowed
50+
a = with pkgs; patchelf;
51+
52+
# disallowed
53+
b = with pkgs; with lib; patchelf;
54+
55+
# also disallowed
56+
c = with pkgs; {
57+
meta = with lib; {
58+
license = with licenses; [ mit ];
59+
};
60+
};
61+
}
62+
```
63+
64+
# Drawbacks
65+
[drawbacks]: #drawbacks
66+
67+
* Backward-incompatible, requires changing Nix code used "in the wild".
68+
69+
# Alternatives
70+
[alternatives]: #alternatives
71+
72+
* Introduce a kind of `with-only` expression which allows bringing an attrset
73+
into scope while simultaneously hiding the outer scope, such that all
74+
inner free variables are either resolved via the given attrset, or
75+
result in an error.
76+
Similar to this is [RFC 110](https://github.com/NixOS/rfcs/pull/110),
77+
which introduces an `inherit-as-list` construct which solves the primary
78+
application of `with-only`, list specification in `meta` attributes of
79+
nixpkgs derivatons.
80+
81+
* Completely ban the usage of `with` in nixpkgs;
82+
seems unnecessarily excessive for this problem.
83+
84+
# Unresolved questions
85+
[unresolved]: #unresolved-questions
86+
87+
Decide if this is enough.
88+
89+
e.g.
90+
* Mutually recursive imports combined with `with` expressions also make static
91+
analysis harder, because they require lazyness at the level of scope lookups,
92+
which is difficult to implement corrently. e.g. [nix2js#2](https://github.com/YZITE/nix2js/issues/2)
93+
* Check if any use case is too much negatively impacted by this.
94+
95+
# Future work
96+
[future]: #future-work
97+
98+
* Static analyzers and transpilers for Nix

0 commit comments

Comments
 (0)