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

deduplicate inherit-from source expr work #9847

Merged
merged 9 commits into from
Feb 26, 2024
Merged

deduplicate inherit-from source expr work #9847

merged 9 commits into from
Feb 26, 2024

Conversation

pennae
Copy link
Contributor

@pennae pennae commented Jan 25, 2024

Motivation

fix #9149. also fix exponential increase in error message size with nested inherit-from expressions. (cc @roberth)

Context

we now allocate an extra env for attrsets containing inherit-from directives for all the from expressions, as a sibling the in-set scope env. this lets us avoid keeping the entire scope around when inherited attributes are picked out, and it makes access to memoized values easier. considering how rare inherit-from are in practice it didn't seem worth the more complicated code needed to allocate one env for each directive.

fun fact: rec { inherit (x) y evaluates x in the inner scope wile rec { inherit y evaluates y in the outer scope. this is inconsistent and feels like an implementation bug that is now become spec by virtue of having been there for way too long.

depends on #9776. seemed more reasonable to not rebase this onto master and have to resolve conflicts after either gets merged.

Priorities and Process

Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@pennae pennae requested a review from edolstra as a code owner January 25, 2024 02:03
@github-actions github-actions bot added the with-tests Issues related to testing. PRs with tests have some priority label Jan 25, 2024
Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will review again as this

src/libexpr/nixexpr.hh Outdated Show resolved Hide resolved
src/libexpr/nixexpr.hh Outdated Show resolved Hide resolved
Copy link

dpulls bot commented Jan 27, 2024

🎉 All dependencies have been resolved !

@roberth
Copy link
Member

roberth commented Jan 27, 2024

@pennae would you mind to rebase this?

@pennae
Copy link
Contributor Author

pennae commented Jan 27, 2024

rebased onto current master. also ran some perf tests, normal operation doesn't notice the change but nix-env -qaP --out-path sees about 5% runtime improvement.

@pennae pennae requested a review from roberth January 31, 2024 22:12
@pennae
Copy link
Contributor Author

pennae commented Feb 3, 2024

@roberth when can we expect a review? this is kind of blocking parser work now (one dependent PR is up, another two in preparation).

@roberth roberth self-assigned this Feb 8, 2024
in place of inherited() — not quite useful yet since we don't
distinguish plain and inheritFrom attr kinds so far.
this also has the effect of sorting let bindings lexicographically
rather than by symbol creation order as was previously done, giving a
better canonicalization in the process.
for plain inherits this is really just a stylistic choice, but for
inherit-from it actually fixes an exponential size increase problem
during expr printing (as may happen during assertion failure reporting,
on during duplicate attr detection in the parser)
@pennae
Copy link
Contributor Author

pennae commented Feb 12, 2024

rebased to fix merge conflicts.

@Ericson2314
Copy link
Member

I think @roberth already knows the answer, but I am surprised this fix seems more involved than I'd imagine

{ inherit (expr) a b c; }

to

let e = expr; in { inherit (e) a b c; }

would be

@pennae
Copy link
Contributor Author

pennae commented Feb 12, 2024

that's basically what this fix is, except that we also collapse the generated envs (for performance reasons) and don't enforce references to the synthetic env on non-inheriting thunks (as are common in nixpkgs where inherit-from is used). lifting the synthetic env from sibling to parent of the entire set would keep it alive much longer than necessary in many cases, and introduce complications with rec sets and lets (which would either need two parent envs or inaccessible elements in their single parent env).

the simplest implementation would've been to create on env per directive, but that would've also been slower (and attrset construction is already not fast because it's overloaded so heavily)

@Ericson2314
Copy link
Member

Thanks @pennae. That makes sense. Basically, I am not used to thinking about these env objects. They feel like something that ought to not exist in a lexically scoped language with just a little bit of work, but maybe I am just being too compiler-brained rather than interpreter-brained about it.

@thufschmitt
Copy link
Member

Discussed during the Nix maintainers meeting on 2024-02-12.
Assigned to @roberth.

Fixing a very weird behaviour on the evaluator (not memoizing the subexpression of inherit).

Agreement that we want it, @roberth to review it

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2024-02-12-nix-team-meeting-minutes-123/39775/1

@pennae
Copy link
Contributor Author

pennae commented Feb 20, 2024

uhm. hello? is this still on anyone's radar or already slipped?

@roberth
Copy link
Member

roberth commented Feb 20, 2024 via email

@pennae
Copy link
Contributor Author

pennae commented Feb 20, 2024

It still is.

then may we humbly request that you either make good on your claim that reviewing a fix for #9149 won't be a problem, or acknowledge that you don't have the capacity to do so and let someone else take over?

Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM.

  • inherited() could be renamed or removed
  • Some suggestions for code comments

Apologies for the delay

src/libexpr/nixexpr.hh Outdated Show resolved Hide resolved
doc/manual/rl-next/inherit-from-by-need.md Outdated Show resolved Hide resolved
src/libexpr/nixexpr.cc Show resolved Hide resolved
src/libexpr/parser.y Outdated Show resolved Hide resolved
src/libexpr/nixexpr.hh Show resolved Hide resolved
@pennae pennae requested a review from roberth February 26, 2024 15:06
Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A typo made it through, but LGTM!

Comment on lines 2 to 6
synopsis: "`inherit (x) ...` evalutates `x` only once"
prs: 9847
---

`inherit (x) a b ...` now evalutates the expression `x` only once for all inherited attributes rather than once for each inherited attribute.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
synopsis: "`inherit (x) ...` evalutates `x` only once"
prs: 9847
---
`inherit (x) a b ...` now evalutates the expression `x` only once for all inherited attributes rather than once for each inherited attribute.
synopsis: "`inherit (x) ...` evaluates `x` only once"
prs: 9847
---
`inherit (x) a b ...` now evaluates the expression `x` only once for all inherited attributes rather than once for each inherited attribute.

desugaring inherit-from to syntactic duplication of the source expr also
duplicates side effects of the source expr (such as trace calls) and
expensive computations (such as derivationStrict).
it's no longer widely used and has a rather confusing meaning now that
inherit-from is handled very differently.
@roberth roberth merged commit 4c7f0ef into NixOS:master Feb 26, 2024
8 checks passed
@roberth
Copy link
Member

roberth commented Feb 26, 2024

Thank you @pennae

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
with-tests Issues related to testing. PRs with tests have some priority
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

inherit duplicates evaluation work
5 participants