sigma-types 0.3.7

Types checked for an invariant.
Documentation
{
  inputs = {
    fenix = {
      url = "github:nix-community/fenix";
      inputs = {
        nixpkgs.follows = "nixpkgs";
        rust-analyzer-src = {
          flake = false;
          url = "github:rust-lang/rust-analyzer/nightly";
        };
      };
    };
    flake-utils.url = "github:numtide/flake-utils";
    nix-filter.url = "github:numtide/nix-filter";
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    treefmt-nix = {
      inputs.nixpkgs.follows = "nixpkgs";
      url = "github:numtide/treefmt-nix";
    };
  };
  outputs =
    {
      fenix,
      flake-utils,
      nix-filter,
      nixpkgs,
      self,
      treefmt-nix,
    }:
    flake-utils.lib.eachDefaultSystem (
      system:
      let
        pname = "sigma-types";
        version = "0.3.7";
        synopsis = "Types checked for an invariant.";
        description = synopsis;
        src = nix-filter {
          root = ./.;
          include = [
            ./Cargo.lock
            ./src
          ];
        };

        pkgs = import nixpkgs {
          inherit system;
          config.allowUnfree = true;
        };
        fenix-toolchain = "default";
        toolchain = fenix.packages.${system}.${fenix-toolchain}.withComponents [
          "cargo"
          "rustc"
        ];
        fenix-full-toolchain = "complete";
        full-toolchain = fenix.packages.${system}.${fenix-full-toolchain}.withComponents [
          "cargo"
          "clippy"
          "miri"
          "rustc"
          "rustfmt"
        ];
        rust-platform = pkgs.makeRustPlatform {
          cargo = toolchain;
          rustc = toolchain;
        };

        ENV = {
          # environment variables:
          MIRIFLAGS = "-Zmiri-disable-isolation";
          RUST_BACKTRACE = "1";
          RUST_LOG = "debug";
        };

        dependencies = { };
        dev-dependencies = {
          paste = {
            features = [ ];
          };
          quickcheck = {
            features = [ ];
          };
          quickcheck_macros = {
            features = [ ];
          };
          serde_json = {
            features = [ "std" ];
          };
        };
        features = {
          malachite = {
            dependencies = {
              malachite-base = {
                features = [ ];
              };
            };
            other-features = [ ];
          };
          quickcheck = {
            dependencies = {
              quickcheck = {
                features = [ ];
              };
            };
            other-features = [ ];
          };
          serde = {
            dependencies = {
              serde = {
                features = [ ];
              };
            };
            other-features = [ ];
          };
          std = {
            dependencies = { };
            other-features = [ ];
          };
        };
        feature-dependencies = builtins.foldl' (
          acc: { dependencies, other-features }: acc // dependencies
        ) { } (builtins.attrValues features);

        tomlize =
          set:
          pkgs.lib.strings.concatLines (
            builtins.filter (s: !builtins.isNull s) (
              builtins.attrValues (
                builtins.mapAttrs (k: v: if builtins.isNull v then null else "${k} = \"${v}\"") set
              )
            )
          );

        cargo-lock = builtins.fromTOML (builtins.readFile ./Cargo.lock);
        dependency-versions = builtins.listToAttrs (
          builtins.map (dependency: {
            inherit (dependency) name;
            value = dependency.version;
          }) cargo-lock.package
        );

        cargo-toml = "Cargo.toml";
        registry-keywords = [
          "no_std"
          "no-std"
          "testing"
          "math"
          "mathematics"
        ];
        registry-categories = [
          "data-structures"
          "development-tools"
          "mathematics"
          "no-std"
          "no-std::no-alloc"
        ];
        override-lints = {
          empty-enum = "allow";
          field-scoped-visibility-modifiers = "allow";
          float-arithmetic = "allow";
          implicit-return = "allow";
          inline-always = "allow";
          map-err-ignore = "allow";
          min-ident-chars = "allow";
          multiple-crate-versions = "allow";
          needless-borrowed-reference = "allow";
          pub-use = null;
          pub-with-shorthand = "allow";
          question-mark-used = "allow";
          redundant-pub-crate = "allow";
          ref-patterns = "allow";
          semicolon-outside-block = "allow";
          separated-literal-suffix = "allow";
          single-char-lifetime-names = "allow";
          tail-expr-drop-order = "warn";
          unknown-lints = "allow";
          unneeded-field-pattern = "allow";
          unqualified-local-imports = null;
          unsafe-code = "allow";
          unstable-features = "allow";
          warnings = "warn";
          wildcard-dependencies = "allow";
        };
        cargo-toml-contents = ''
          [package]
          name = "${pname}"
          version = "${version}"
          edition = "2024"
          publish = true
          authors = [ "Will Sturgeon" ]
          description = "${description}"
          readme = "README.md"
          homepage = "https://github.com/wrsturgeon/${pname}"
          repository = "https://github.com/wrsturgeon/${pname}"
          license = "MPL-2.0"
          keywords = [ "${pkgs.lib.strings.concatStringsSep "\", \"" registry-keywords}" ]
          categories = [ "${pkgs.lib.strings.concatStringsSep "\", \"" registry-categories}" ]

          [dependencies]
          ${pkgs.lib.strings.concatLines (
            builtins.attrValues (
              builtins.mapAttrs (
                pkg: attrs:
                "${pkg} = { version = \"${
                  if builtins.hasAttr pkg dependency-versions then dependency-versions.${pkg} else "*"
                }\", default-features = false, features = [ ${
                  pkgs.lib.strings.concatStringsSep ", " (builtins.map (feature: "\"${feature}\"") attrs.features)
                } ]${if attrs ? git then ", git = \"${attrs.git}\"" else ""} }"
              ) dependencies
            )
          )}
          ${pkgs.lib.strings.concatLines (
            builtins.attrValues (
              builtins.mapAttrs (
                pkg: attrs:
                "${pkg} = { version = \"${
                  if builtins.hasAttr pkg dependency-versions then dependency-versions.${pkg} else "*"
                }\", default-features = false, features = [ ${
                  pkgs.lib.strings.concatStringsSep ", " (builtins.map (feature: "\"${feature}\"") attrs.features)
                } ]${if attrs ? git then ", git = \"${attrs.git}\"" else ""}, optional = true }"
              ) feature-dependencies
            )
          )}
          [dev-dependencies]
          ${pkgs.lib.strings.concatLines (
            builtins.attrValues (
              builtins.mapAttrs (
                pkg: attrs:
                "${pkg} = { version = \"${
                  if builtins.hasAttr pkg dependency-versions then dependency-versions.${pkg} else "*"
                }\", default-features = false, features = [ ${
                  pkgs.lib.strings.concatStringsSep ", " (builtins.map (feature: "\"${feature}\"") attrs.features)
                } ]${if attrs ? git then ", git = \"${attrs.git}\"" else ""} }"
              ) dev-dependencies
            )
          )}
          [features]
          ${pkgs.lib.strings.concatLines (
            builtins.attrValues (
              builtins.mapAttrs (
                k:
                { dependencies, other-features }:
                "${k} = [ ${
                  pkgs.lib.strings.concatStringsSep ", " (
                    builtins.map (s: "\"${s}\"") (
                      other-features ++ builtins.map (s: "dep:${s}") (builtins.attrNames dependencies)
                    )
                  )
                } ]"
              ) features
            )
          )}
        '';
        update-cargo-toml = "echo ${pkgs.lib.strings.escapeShellArg cargo-toml-contents} > ${cargo-toml}";

        full-src = pkgs.stdenvNoCC.mkDerivation {
          pname = "full-src";
          inherit version;
          inherit src;
          buildPhase = update-cargo-toml;
          installPhase = "cp -r . $out";
        };

        treefmt = treefmt-nix.lib.evalModule pkgs ./.treefmt.nix;

      in
      {
        apps =
          builtins.mapAttrs
            (name: script: {
              meta.description = name;
              type = "app";
              program =
                let
                  full-script = ''
                    #!${pkgs.bash}/bin/bash
                    set -eu
                    set -o pipefail
                    ${script}
                  '';
                  written = pkgs.writeScriptBin name full-script;
                in
                "${written}/bin/${name}";
            })
            {
              inherit update-cargo-toml;

              miri = ''
                export QUICKCHECK_TESTS=10
                cargo miri test
                cargo miri test --release
                cargo miri test --all-features
                cargo miri test --all-features --release
              '';

              test = ''
                cargo test
                cargo test --release
                cargo test --all-features
                cargo test --all-features --release
              '';

              update-other-cargo-files =
                let
                  rust-toolchain-toml = ''
                    [toolchain]
                    channel = "nightly"
                  '';
                in
                ''
                  echo ${pkgs.lib.strings.escapeShellArg rust-toolchain-toml} > rust-toolchain.toml
                '';
              clippy = ''
                set +e
                ${pkgs.ripgrep}/bin/rg 'let &' --iglob='!flake\.nix'
                if [ "$?" -eq 0 ]
                then
                  echo 'Found `let &`. Exiting as an error.'
                  exit 1
                fi
                set -ex

                # No features:
                ${full-toolchain}/bin/cargo-clippy -- --all-targets --color=always --no-default-features
                ${full-toolchain}/bin/cargo-clippy -- --all-targets --color=always --no-default-features --release
                ${
                  if features ? std then
                    ''
                      # No features except the standard library:
                      ${full-toolchain}/bin/cargo-clippy -- --all-targets --color=always --no-default-features --features=std
                      ${full-toolchain}/bin/cargo-clippy -- --all-targets --color=always --no-default-features --features=std --release
                    ''
                  else
                    ""
                }
                # All features that don't use the standard library:
                ${full-toolchain}/bin/cargo-clippy -- --all-targets --color=always --no-default-features --features=${
                  builtins.concatStringsSep "," (
                    builtins.filter (f: f != "std" && !(builtins.any (f: f == "std") features.${f}.other-features)) (
                      builtins.attrNames features
                    )
                  )
                }
                ${full-toolchain}/bin/cargo-clippy -- --all-targets --color=always --no-default-features --features=${
                  builtins.concatStringsSep "," (
                    builtins.filter (f: f != "std" && !(builtins.any (f: f == "std") features.${f}.other-features)) (
                      builtins.attrNames features
                    )
                  )
                } --release
                # All features, including those that might use the standard library:
                ${full-toolchain}/bin/cargo-clippy -- --all-targets --color=always --all-features
                ${full-toolchain}/bin/cargo-clippy -- --all-targets --color=always --all-features --release
              '';
            };
        packages.default = rust-platform.buildRustPackage (
          ENV
          // (
            let
              src = full-src;
            in
            {
              inherit pname src;
              name = pname;
              cargoLock.lockFile = "${src}/Cargo.lock";
            }
          )
        );
        devShells.default = pkgs.mkShell (
          ENV
          // {
            inputsFrom = builtins.attrValues self.packages.${system};
            packages = with pkgs; [
              full-toolchain
              lldb
              rust-analyzer
            ];
          }
        );
        formatter = treefmt.config.build.wrapper;
      }
    );
}