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

Convert libs to a fixed-point #27797

Merged
merged 1 commit into from Sep 19, 2017
Merged

Convert libs to a fixed-point #27797

merged 1 commit into from Sep 19, 2017

Conversation

grahamc
Copy link
Member

@grahamc grahamc commented Jul 31, 2017

This does break the API of being able to import any lib file and get
its libs, however I'm not sure people did this.

I made this while exploring being able to swap out docFn with a stub
in #2305, to avoid functor performance problems. I don't know if that
is going to move forward (or if it is a problem or not,) but after
doing all this work figured I'd put it up anyway :)

Two notable advantages to this approach:

  1. when a lib inherits another lib's functions, it doesn't
    automatically get put in to the scope of lib
  2. when a lib implements a new obscure functions, it doesn't
    automatically get put in to the scope of lib
Things done

Please check what applies. Note that these are not hard requirements but merely serve as information for reviewers.

  • Tested using sandboxing
    (nix.useSandbox on NixOS,
    or option build-use-sandbox in nix.conf
    on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • Linux
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Fits CONTRIBUTING.md.

@shlevy
Copy link
Member

shlevy commented Jul 31, 2017

Hmm, not quite sure I see the benefit here but no strong objections either.

@grahamc
Copy link
Member Author

grahamc commented Jul 31, 2017

Yeah, the benefit is limited, but in cases of the function fixedWidthString which yes does belong in strings.nix but no doesn't have any business being "exported" by default to lib.fixedWidthString. This, and fewer important statements seems like all the benefit there is. Pretty anemic set of reasons.

I mostly put it up in case someone else had a convincing reason :)

Copy link
Member

@aszlig aszlig left a comment

Choose a reason for hiding this comment

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

I don't have very strong objections either, but the new version of the default.nix now looks a lot messier to me than it was before. If a function shouldn't be available from outside, isn't it better to put it inside of a let?

lib/default.nix Outdated

# back-compat aliases
platforms = systems.doubles;
}
};
in lib // (with lib; {}
# !!! don't include everything at top-level; perhaps only the most
# commonly used functions.
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this comment obsolete with this change?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops leftover from when I was in the middle of the conversion. Fixed.

lib/modules.nix Outdated
with (lib.attrsets);
with (lib.options);
with (lib.debug);
with (lib.types);
Copy link
Member

Choose a reason for hiding this comment

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

The parentheses are unnecessary here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

lib/default.nix Outdated

# back-compat aliases
platforms = systems.doubles;
}
};
in lib // (with lib; {}
Copy link
Member

Choose a reason for hiding this comment

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

Also, this (with lib; {}) doesn't make sense to me either.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops leftover from when I was in the middle of the conversion. Fixed.

lib/default.nix Outdated

# back-compat aliases
platforms = systems.doubles;
}
};
in lib // (with lib; {}
Copy link
Contributor

Choose a reason for hiding this comment

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

What's this with lib; {} for?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops leftover from when I was in the middle of the conversion. Fixed.

@grahamc grahamc force-pushed the fixed-lib branch 2 times, most recently from 4dc091b to 9a0e632 Compare July 31, 2017 11:22
@grahamc
Copy link
Member Author

grahamc commented Jul 31, 2017

If a function shouldn't be available from outside, isn't it better to put it inside of a let?

An example is lib.strings.fixedWidthString has every right to exist and be usable externally, but has no business being hoisted up to lib.fixedWidthString. This is the spirit of

!!! don't include everything at top-level; perhaps only the most
commonly used functions.

but the reality is that comment is impossible to accomplish with the current structure.

@grahamc
Copy link
Member Author

grahamc commented Jul 31, 2017

@aszlig I added a commit where I tried your suggestion of moving the inherits to the bottom.

Copy link
Member

@aszlig aszlig left a comment

Choose a reason for hiding this comment

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

Okay, that at least makes it a bit easier on the eyes :-)

@aszlig
Copy link
Member

aszlig commented Jul 31, 2017

👍 after clarification on IRC what this PR actually improves:

gchristensen: a concrete example is lib.strings.tail exists because of https://github.com/NixOS/nixpkgs/pull/27797/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR11
gchristensen: another gross thing is types.nix has types = {} inside it

@grahamc
Copy link
Member Author

grahamc commented Jul 31, 2017

On IRC, @edolstra said that the massive list of inherits is ugly, but probably unavoidable due to the lack of laziness in with lib. I clarified with him and he's okay with this change and the ugliness isn't a blocking problem for the merge.

Unless there is further feedback, I'm planning on merging this later today or tomorrow.

@grahamc grahamc requested a review from nbp July 31, 2017 12:54
Copy link
Member

@LnL7 LnL7 left a comment

Choose a reason for hiding this comment

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

Since this makes the functions exposed in lib explicit now should we add a deprecation notice to the functions that obviously don't belong there?

Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

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

Ah, I was hoping somebody would remove the extra imports eventually! Besides the other benefits, this should speed up evaluation a bit.

@grahamc
Copy link
Member Author

grahamc commented Aug 1, 2017

@fpletz what sort of docs and changelog would you like to see?

@fpletz
Copy link
Member

fpletz commented Aug 1, 2017

@grahamc I haven't looked at the manuals yet but this change at least deserves a paragraph in the nixpkgs manual. We should also mention this in the NixOS 17.09 release notes.

@grahamc
Copy link
Member Author

grahamc commented Aug 2, 2017

I suppose I'm having a hard time writing the docs because not much has changed. Maybe:

It is now required to import the top level lib library instead of individual library sets. Before you could import <nixpkgs/lib/attrsets.nix> and you must now (import <nixpkgs/lib>).attrsets.

@grahamc
Copy link
Member Author

grahamc commented Aug 2, 2017

I've used the following to verify the same attributes are being exported on lib:

[nix-shell:~/projects/nixpkgs]$ git checkout fixed-lib
Already on 'fixed-lib'

[nix-shell:~/projects/nixpkgs]$ echo "import ./lib" | nix-repl 2>&1 | tr ' ' $'\n' | sort | uniq > ../fixed-lib

[nix-shell:~/projects/nixpkgs]$ git checkout origin/master
Note: checking out 'origin/master'.
HEAD is now at 87b215d5f72... android-studio-preview: 3.0.0.7 -> 3.0.0.8

[nix-shell:~/projects/nixpkgs]$ echo "import ./lib" | nix-repl 2>&1 | tr ' ' $'\n' | sort | uniq > ../master

[nix-shell:~/projects/nixpkgs]$ diff ../fixed-lib ../master

[nix-shell:~/projects/nixpkgs]$ 

unfortunately this isn't recursive, looks like I have more testing to do:

10,11d9
<  defaultFunctor = «lambda»
<  defaultTypeMerge = «lambda»
16,17d13
<  isOptionType = «lambda»
<  isType = «lambda»
25d20
<  mkOptionType = «lambda»
31d25
<  setType = «lambda»
36d29
<  types = { ... }

on types.

This does break the API of being able to import any lib file and get
its libs, however I'm not sure people did this.

I made this while exploring being able to swap out docFn with a stub
in NixOS#2305, to avoid functor performance problems. I don't know if that
is going to move forward (or if it is a problem or not,) but after
doing all this work figured I'd put it up anyway :)

Two notable advantages to this approach:

1. when a lib inherits another lib's functions, it doesn't
   automatically get put in to the scope of lib
2. when a lib implements a new obscure functions, it doesn't
   automatically get put in to the scope of lib

Using the test script (later in this commit) I got the following diff
on the API:

  + diff master fixed-lib
  11764a11765,11766
  > .types.defaultFunctor
  > .types.defaultTypeMerge
  11774a11777,11778
  > .types.isOptionType
  > .types.isType
  11781a11786
  > .types.mkOptionType
  11788a11794
  > .types.setType
  11795a11802
  > .types.types

This means that this commit _adds_ to the API, however I can't find a
way to fix these last remaining discrepancies. At least none are
_removed_.

Test script (run with nix-repl in the PATH):

  #!/bin/sh

  set -eux

  repl() {
      suff=${1:-}
      echo "(import ./lib)$suff" \
          | nix-repl 2>&1
  }

  attrs_to_check() {
      repl "${1:-}" \
          | tr ';'  $'\n' \
          | grep "\.\.\." \
          | cut -d' ' -f2 \
          | sed -e "s/^/${1:-}./" \
          | sort
  }

  summ() {
      repl "${1:-}" \
          | tr ' ' $'\n' \
          | sort \
          | uniq
  }

  deep_summ() {
      suff="${1:-}"
      depth="${2:-4}"
      depth=$((depth - 1))
      summ "$suff"

      for attr in $(attrs_to_check "$suff" | grep -v "types.types"); do
          if [ $depth -eq 0 ]; then
              summ "$attr" | sed -e "s/^/$attr./"
          else
              deep_summ "$attr" "$depth" | sed -e "s/^/$attr./"
          fi
      done
  }

  (
      cd nixpkgs

      #git add .
      #git commit -m "Auto-commit, sorry" || true
      git checkout fixed-lib
      deep_summ > ../fixed-lib
      git checkout master
      deep_summ > ../master
  )

  if diff master fixed-lib; then
      echo "SHALLOW MATCH!"
  fi

  (
      cd nixpkgs
      git checkout fixed-lib
      repl .types
  )
@grahamc
Copy link
Member Author

grahamc commented Sep 17, 2017

An update, and good news!

Using the test script (later in this commenet) I got the following diff
on the API:

  + diff master fixed-lib
  11764a11765,11766
  > .types.defaultFunctor
  > .types.defaultTypeMerge
  11774a11777,11778
  > .types.isOptionType
  > .types.isType
  11781a11786
  > .types.mkOptionType
  11788a11794
  > .types.setType
  11795a11802
  > .types.types

This means that this commit adds to the API, however I can't find a
way to fix these last remaining discrepancies. At least none are
removed.

The test script recursively explores attribute keys (with crude loop prevention) and produces the same diff for 10 recursions (though the pasted script does 4).

Test script (run with nix-repl in the PATH):

  #!/bin/sh

  set -eux

  repl() {
      suff=${1:-}
      echo "(import ./lib)$suff" \
          | nix-repl 2>&1
  }

  attrs_to_check() {
      repl "${1:-}" \
          | tr ';'  $'\n' \
          | grep "\.\.\." \
          | cut -d' ' -f2 \
          | sed -e "s/^/${1:-}./" \
          | sort
  }

  summ() {
      repl "${1:-}" \
          | tr ' ' $'\n' \
          | sort \
          | uniq
  }

  deep_summ() {
      suff="${1:-}"
      depth="${2:-4}"
      depth=$((depth - 1))
      summ "$suff"

      for attr in $(attrs_to_check "$suff" | grep -v "types.types"); do
          if [ $depth -eq 0 ]; then
              summ "$attr" | sed -e "s/^/$attr./"
          else
              deep_summ "$attr" "$depth" | sed -e "s/^/$attr./"
          fi
      done
  }

  (
      cd nixpkgs

      #git add .
      #git commit -m "Auto-commit, sorry" || true
      git checkout fixed-lib
      deep_summ > ../fixed-lib
      git checkout master
      deep_summ > ../master
  )

  if diff master fixed-lib; then
      echo "SHALLOW MATCH!"
  fi

  (
      cd nixpkgs
      git checkout fixed-lib
      repl .types
  )

@grahamc
Copy link
Member Author

grahamc commented Sep 17, 2017

Heads up: I'm planning on merging this on Tuesday unless someone asks me not to :)

@grahamc
Copy link
Member Author

grahamc commented Sep 19, 2017

Final warning: I'll be merging this in between 12 and 24 hours.

@Ericson2314 Ericson2314 added the 9.needs: port to stable A PR needs a backport to the stable release. label Sep 19, 2017
@Ericson2314 Ericson2314 merged commit bc9f471 into NixOS:master Sep 19, 2017
@grahamc grahamc deleted the fixed-lib branch September 19, 2017 15:05
@samueldr samueldr removed the 9.needs: port to stable A PR needs a backport to the stable release. label Apr 17, 2019
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

9 participants