This class only served one purpose, to avoid typing the name of the
option twice. Unfortunately the way it was implemented made getting the
type checking right difficult, and required storing the same data twice.
This patch replaces this approach with a dictionary comprehension that
creates the OptionKey from the UserOption. This allows us to initialize
a single dictionary once, avoid typing the name twice, delete lines of
code, and get better type safety.
As an added bonus, it means that the exported data from the module can
be marked module constant, ie, ALL_CAPS.
These options are stored as a "global" options, ie, subproject=None.
Therefore, the call to `as_root()` could never be correct, and only the
`k in base_options` check could ever be correct. Since these options are
not supposed to be set here in the root project or in subprojects, we
want to check for the global option and skip.
This gives us a simpler way to annotate things returning an option
value, and gives us an easy single place to change that will affect
everywhere if the option value types are changed.
The fact that UserOption is generic is really an implementation detail,
not something to be used publicly. So by having an `AnyOptionType`
alias, we can get better type checking, as can be seen by the patch as a
whole. One of the big fixes it replace open-coded equivlalents of
`MutableKeydOptionDictType` with that type alias.
Which wants a string, but then passes that string to a function that
wants an OptionKey, which means that we'll always miss the lookup in
BULITIN_DIR_NOPREFIX_OPTIONS, and return the default. The only case this
gets used we cast an OptionKey to str, and then pass that. So instead,
do the cast inside the function when necessary and pass the OptionKey
This reduces code, makes this clearer, and will be a nice step toward
the goal of getting everything typesafe.
For `UserIntegerOption` this makes a fairly nice, but substantial change
in that the old method used a tuple of `(min, value, max)` to pass to the
initializer, while all other types just passed `value`. The new
`UserIntegerOption` does the same, with keyword arguments for the min
and max values.
It is generally accepted practice to convert dict.keys() to a list
before iterating over it and e.g. deleting values, as keys returns a
live-action view. In this case, we use the difference of *two* dict
keys, which returns a regular non-view set and doesn't need protecting.
Iteration order doesn't matter (the set already randomizes it anyway).
Avoid the cost of converting to a list.
When we load the option file in the interpreter record which file it
was, and what the hash of that file was. This will let `meson configure`
know that the options have changed since the last re-configure.
By adding the option name to UserOption object, it is now possible to
display the name of the affected option when the given option value is
not valid.
Fixes#12635