WEYL WEYL
← Back to Weyl Standard
guides

Forbidden Patterns

These patterns are explicitly prohibited in Weyl Standard Nix to avoid common pitfalls and maintain code quality.

Forbidden Patterns

These patterns are explicitly prohibited in Weyl Standard Nix.

with Statements

FORBIDDEN (except in short list contexts).

# NON-CONFORMANT
with lib;
with pkgs;
{
options.foo = mkOption { type = types.str; };
}
# CONFORMANT
let
inherit (lib) mkOption types;
in
{
options.foo = mkOption { type = types.str; };
}

Rationale

Exception

Short lists where the source is obvious:

environment.systemPackages = with pkgs; [
vim
git
curl
];

rec in Derivations

FORBIDDEN.

# NON-CONFORMANT
stdenv.mkDerivation rec {
pname = "my-tool";
version = "1.0.0";
src = fetchFromGitHub {
rev = "v${version}";
};
}
# CONFORMANT
stdenv.mkDerivation (finalAttrs: {
pname = "my-tool";
version = "1.0.0";
src = fetchFromGitHub {
rev = "v${finalAttrs.version}";
};
})

Rationale

With rec, overrideAttrs doesn’t work correctly. The version reference is baked in at definition time, not resolved after overrides.

if/then/else in Module Config

FORBIDDEN.

# NON-CONFORMANT
config = if cfg.enable then {
services.foo.enable = true;
} else {};
# CONFORMANT
config = mkIf cfg.enable {
services.foo.enable = true;
};

Rationale

Eager evaluation causes infinite recursion when modules reference each other’s options.

Import From Derivation (IFD)

FORBIDDEN.

# NON-CONFORMANT
let
generated = pkgs.runCommand "gen.nix" {} ''echo "{ x = 1; }" > $out'';
in
import generated

Rationale

IFD forces builds during evaluation. This breaks:

default.nix in packages/

FORBIDDEN (except in nix/overlays/).

# NON-CONFORMANT
nix/packages/
├── my-tool/
│ └── default.nix
# CONFORMANT
nix/packages/
├── my-tool.nix

Rationale

The filename becomes the attribute name. default.nix discards this information.

Configuring nixpkgs Outside weyl-std

FORBIDDEN.

# NON-CONFORMANT
perSystem = { system, ... }: {
_module.args.pkgs = import inputs.nixpkgs {
inherit system;
config.cudaSupport = true; # NO
};
};
# CONFORMANT
perSystem = { system, ... }: {
_module.args.pkgs = inputs.weyl-std.nixpkgs.${system};
};

Rationale

Central nixpkgs configuration ensures CUDA versions, capabilities, and overlays are consistent across the entire stack. Per-flake configuration creates version mismatches.

Overriding nixpkgs Config in NixOS

FORBIDDEN.

# NON-CONFORMANT
{ ... }:
{
nixpkgs.config.cudaSupport = false; # NO
}

Rationale

NixOS configs receive their pkgs from the flake via nixpkgs.pkgs. Overriding config at the NixOS level breaks consistency.

Inline Foreign Code Over 10 Lines

FORBIDDEN.

# NON-CONFORMANT
buildPhase = ''
#!/bin/bash
# ... 50 lines of bash ...
'';
# CONFORMANT
buildPhase = builtins.readFile ./build.sh;

Rationale

Inline strings:

Summary Table

PatternReason
with lib;Obscures provenance, breaks tooling
rec in derivationsBreaks overrideAttrs
if/then/else in module configEager evaluation causes infinite recursion
Import from derivationForces builds during evaluation
default.nix in packagesDiscards filename information
Per-flake nixpkgs configCreates version mismatches
camelCase in weyl namespacesViolates naming convention
Missing _classSilent cross-module-system failures
Missing meta in packagesBreaks documentation and compliance
Inline code >10 linesUntestable, unlintable