Confusing behavior of aliases when evaluating modules with evalModules

test.nix:

lib:

with lib;

let

  someModule = {
    options.foo = mkOption {
      type = types.bool;
      default = true;
    };
  };

in

evalModules {
  modules =
    [ someModule
      (mkAliasOptionModule [ "bar" ] [ "foo" ])
    ];
  check = false;
}

Let’s load it in the REPL:

nix-repl> :l <nixpkgs>
Added 10082 variables.

nix-repl> cfg = import ./test.nix lib

nix-repl> cfg.config.foo
true

nix-repl> cfg.config.bar
error: The option `bar' is used but not defined.

The option bar is defined as an alias of foo. How can it be that foo is defined but bar is not?
I’m using NixOS 19.03.

Looking at the definition of mkAliasOptionModule, it appears that all definitions of bar get propagated to foo, but not vice versa, which is why bar is not defined. I find this confusing, because I thought that "option a is an alias of option b" means "option a is the same option as option b", i.e. every definition of a counts as a definition of b and vice versa. I feel like this is a bug that should be fixed.

Ok, I’m pretty sure this is a bug, here’s why:

  1. mkAliasOptionModule sets the apply attribute of the newly created option (code), so that when its value is computed, it evaluates to the value of the target option. So, in principle, evaluating cfg.config.bar should evaluate to exactly the same thing as cfg.config.foo.
  2. This doesn’t happen, because the option bar does not have any definitions, and the apply attribute of the option isn’t used (code).

A workaround would be for mkAliasOptionModule to define the newly created option, but give it a very high priority number (so that its priority is very low) and a value that throws an error when evaluated.

I’ve created an issue on github.