Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC 0120] Discourage nested with expressions #120

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions rfcs/0120-no-nested-with.md
Original file line number Diff line number Diff line change
@@ -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.
fogti marked this conversation as resolved.
Show resolved Hide resolved

# 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.
fogti marked this conversation as resolved.
Show resolved Hide resolved