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

treewide: expunge functions from platforms #238331

Closed
wants to merge 3 commits into from
Closed

treewide: expunge functions from platforms #238331

wants to merge 3 commits into from

Conversation

ghost
Copy link

@ghost ghost commented Jun 17, 2023

Cc: @roberth @Artturin @sternenseemann

Description of changes

This commit moves canExecute, emulator, and emulatorAvailable out of {host,build,target}Platform and lifts them into lib.systems. Stubs have been left behind to assist with migration of out-of-tree code.

Nix's function equality is unpredictable and error-prone; we should not rely on it. Since we need to be able to test {host,build,target}Platform attrsets for equality, the most sustainable long-term solution is to forbid functions from these attrsets, much like we do for the meta attrset.

Things done
  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 23.11 Release Notes (or backporting 23.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

lib/systems/default.nix Outdated Show resolved Hide resolved
Copy link
Member

@sternenseemann sternenseemann left a comment

Choose a reason for hiding this comment

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

Excellent!

  • With 5d8e668, the issue described in stdenv: fix crossSystem localSystem comparison #237427 should disappear and we'd be able to revert lib.systems.equals #237512 for good (and live worriless when the functions are finally removed after a deprecation period of one or two releases, I guess).
  • We should add polyfills to 23.11, so backporting cross changes becomes easier. These would have the form: canExecute = machinePlatform: machinePlatform.canExecute etc. This wouldn't break anything, but would ideally make backported changes just work (as long as they apply)

lib/systems/default.nix Outdated Show resolved Hide resolved
nixos/doc/manual/release-notes/rl-2311.section.md Outdated Show resolved Hide resolved
pkgs/top-level/all-packages.nix Outdated Show resolved Hide resolved
canExecute = canExecutePlaceholder final;

# 2023-06-17: `platform.emulatorAvailable` has been removed in favor of `lib.systems.emulatorAvailable platform`
emulatorAvailable = emulatorAvailablePlaceholder final;
Copy link
Member

Choose a reason for hiding this comment

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

These also don't need to be placeholders, right?

Copy link
Author

@ghost ghost Nov 4, 2023

Choose a reason for hiding this comment

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

These were added by @sternenseemann here: #238331 (review) in commit 5d8e668

They do need to be placeholders, because they are functions. And Nix's definition of equality for functions is crackheaded.

Copy link
Author

Choose a reason for hiding this comment

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

See 5d8e668#diff-2165823a8d82c5dd1353601bd290df8bd431f9ee2096750d9ef655cf5d251998R37-R47

 # These definitions have to be floated out into a `let … in` binding to ensure
 # that they are the same exact value struct in the evaluating Nix
 # implementation. Due to a quirk in how equality is implemented, values including
 # functions are considered equal if they have the same memory location as long as
 # they are inside a container value and not compared directly. Thus any attribute
 # set will compare equal to itself even if it contains functions.
 # By floating the functions out of the attribute set construction we'll ensure
 # that the functions have the same memory location regardless of what call to
 # lib.systems.elaborate produced them. This ensures that platform sets will be
 # equal even if they have been constructed by different calls to lib.systems.elaborate
 # —as long as their other contents are the same.

Copy link
Member

Choose a reason for hiding this comment

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

Ugh, right.

lib/systems/default.nix Outdated Show resolved Hide resolved
lib/systems/default.nix Show resolved Hide resolved
@ghost ghost requested a review from alyssais November 4, 2023 02:15
@ghost ghost marked this pull request as draft November 4, 2023 02:33
@ghost
Copy link
Author

ghost commented Nov 4, 2023

Rebased

@ghost ghost marked this pull request as ready for review November 4, 2023 02:53
Copy link
Member

@alyssais alyssais left a comment

Choose a reason for hiding this comment

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

That's my last comment — consider me to have approved the PR once that's fixed and the commits are squashed.

I've only reviewed the changes in lib/systems. I'm trusting you to have done the mechanical replacement in the rest of the tree correctly.

lib/systems/default.nix Outdated Show resolved Hide resolved
@ghost
Copy link
Author

ghost commented Nov 4, 2023

Rebased, squashed.

@ghost ghost requested a review from alyssais November 4, 2023 08:51
Copy link
Member

@alyssais alyssais left a comment

Choose a reason for hiding this comment

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

Again, I've only taken a very cursory look outside of lib/systems.

roberth
roberth previously requested changes Nov 6, 2023
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.

I wish I didn't have to repeat myself. my bad, please ignore

lib/systems/default.nix Outdated Show resolved Hide resolved
parse = import ./parse.nix { inherit lib; };

# uncomment after 23.11 branch-off
Copy link
Member

Choose a reason for hiding this comment

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

To be kind to external users supporting both stable and unstable, these shouldn't be made warnings until after 24.05 is branched off, and errors after 24.11 is branched off, right?

Copy link
Author

@ghost ghost Nov 7, 2023

Choose a reason for hiding this comment

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

To be kind to external users supporting both stable and unstable, these shouldn't be made warnings until after 24.05 is branched off, and errors after 24.11 is branched off, right?

I was actually hoping to get the lib.warn in before the 23.11 branch-off, since lib.warn is only a hard CI failure for nixpkgs itself.

Since lib.warn is our way of giving a heads-up to people downstream of us, anybody who has their CI set up to fail if nixpkgs emits a warning is basically turning anything sent across our only communication channel into breakage. I think that's a bad choice and I don't think many users choose it (for very long).

So ideally I'd like to put the lib.warn in before 23.11 branch-off.

The timeline for the removal of these attributes is less urgent; if that needs to wait until after 23.11 I guess that's okay. Keep in mind however that until these attributes are removed, we have no way to lib.warn on any deprecated attributes of system objects (like isEfi), because removeFunctions needs to use lib.isFunction and there is no way to write it which is (AFAICT) lazy enough to not emit the warning. So any deprecations of platform attributes cause nixpkgs CI to fail.

Ultimately, if people really want even the lib.warn to wait until after 23.11, then I guess it has to wait.

Even though this PR has two approvals I will not merge it myself.

Edit: oh, I see, if this PR merges as-is there is no way to write code that works and does not emit warnings on both 23.05 and the post-merge-of-this-PR tree.

Okay I will update this to account for that.

Copy link
Author

Choose a reason for hiding this comment

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

Alright, let me know if 1f7f6d3 captures this intent correctly.

@ghost ghost marked this pull request as draft November 7, 2023 01:39
@ghost ghost marked this pull request as ready for review November 7, 2023 01:43
@ghost ghost requested a review from alyssais November 7, 2023 01:43
Adam Joseph and others added 2 commits November 17, 2023 02:58
This commit moves `canExecute`, `emulator`, and `emulatorAvailable`
out of `{host,build,target}Platform` and lifts them into
`lib.systems`.  Stubs have been left behind to assist with migration
of out-of-tree code.

Nix's function equality is unpredictable and error-prone; we should
not rely on it.  Since we need to be able to test
`{host,build,target}Platform` attrsets for equality, the most
sustainable long-term solution is to forbid functions from these
attrsets, much like we do for the `meta` attrset.

The stubs which have been left behind are a narrowly-defined case
where Nix's function equality *does* behave predictably.
Comparing platform sets using `==` works for most cases since the in the
native case, the platform sets would not only be equal, but the same
identical value (in terms of memory location). This is, however,
technically not always the case, e.g. when specifying crossSystem
explicitly, cases can arise when we should use a native stdenv, but
don't since the functions wouldn't compare as equal due to them being
constructed in separate invocations of `lib.system.elaborate`. This
problem is described in #237427 and motivated #237512 as an equality
predicate that ignors the functions.

Since the functions in the platform attribute set no longer relate to
the platform set at all, we can use the same function value for every
placeholder deprecation error function in the attribute set—consequently
they will all compare as equal even for independently constructed
platform sets.

This is achieved by floating the funtions into a let binding in
`lib/systems/default.nix`, ensuring that they are only constructed once
per nixpkgs instance, i.e. when that file is imported. (Consequently,
comparison of platform sets should be reliable as long as they come from
the same instance of nixpkgs.)

    let
      inherit (
        import <nixpkgs> {
          localSystem = "x86_64-linux";
          crossSystem.system = "x86_64-linux";
        }
      ) buildPlatform
        hostPlatform
        ;
    in

    buildPlatform == hostPlatform
    # => true

This property is also verified with new test cases.
@ghost ghost marked this pull request as draft November 17, 2023 11:00
@ghost
Copy link
Author

ghost commented Nov 17, 2023

Fixed merge conflict.

@ghost ghost marked this pull request as ready for review November 17, 2023 11:01
@ghost ghost requested a review from ncfavier as a code owner November 17, 2023 11:01
This commit moves `canExecute`, `emulator`, and `emulatorAvailable`
out of `{host,build,target}Platform` and lifts them into
`lib.systems`.  Stubs have been left behind to assist with migration
of out-of-tree code.  These will be changed to `lib.warn` or
`throw`, but that change will not be backported to 23.05.

Nix's function equality is unpredictable and error-prone; we should
not rely on it.  Since we need to be able to test
`{host,build,target}Platform` attrsets for equality, the most
sustainable long-term solution is to forbid functions from these
attrsets, much like we do for the `meta` attrset.
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.

We should move the first date a bit, because for a month we support all three versions: 23.05, 23.11, unstable.

Maybe it'd be more clear to make the 23.05 EOL changes in a draft PR instead of commented code.
Perhaps link the PR in a comment if you still want to provide context for readers of the code.

emulatorPlaceholder = _: throw "2023-06-17: `platform.emulator` has been removed in favor of `lib.systems.emulator platform`";
*/

# uncomment after 23.11 branch-off
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
# uncomment after 23.11 branch-off
# uncomment in January 2024, after 23.05 EOL

*/

# uncomment after 23.11 branch-off
# delete after 24.05 branch-off
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
# delete after 24.05 branch-off
# delete canExecutePlaceholder, emulatorAvailablePlaceholder and emulatorPlaceholder after 24.05 branch-off (throwing would have been nice, but throws off `==` equality when comparing platforms elaborated on distinct but compatible Nixpkgs source trees)
  • Won't be grouped by the comment syntax anymore, so be explicit
  • Explain why not throw in this case

@@ -64,6 +64,33 @@ lib.runTests (
testunix = mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ cygwin ++ redox);
})


# Uncomment after 23.11
Copy link
Member

Choose a reason for hiding this comment

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

I think this needs to be in sync with the other uncomment comment.

Suggested change
# Uncomment after 23.11
# Uncomment after 23.05 EOL in January 2024

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants