throwIf sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
assertMsg sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
- Improve extractItem error messages: distinguish non-attrset elements
from multi-key attrsets, and include the faulty definition via showDefs.
- Use isType instead of raw _type access for order detection.
- Disable type merging (typeMerge = t: null) instead of providing a
functor-based merge. Add test confirming duplicate declarations fail.
This allows the type's return value to be accessed more easily.
Motivating use case:
- Built-in module provides CLI functionality by declaring
an `attrListWith { asAttrs = true; }`, extracting the ordered list
from `valueMeta` for the purpose of creating the `argv`.
- User modules can read the command line's flags directly without
having to parse the list of attrs.
This adds a type for name-value mappings that preserve ordering.
Motivating use case: command line flags for package modules /
wrappers / modular services.
The option value can be transformed into a command line in the
correct order.
Additionally, a convenience readOnly option could be provided
to give easy introspection access to the values in an ad hoc
manner.
The only place `merged` is used already checks if `coercedType.merge ?
v2`, so we don't need to check it again. We can also avoid creating the
variable if coercedTypes.merge doesn't have a v2 attribute.
`emptyValue` for `types.submodule` was `{ value = { }; }`, i.e. none
of the type-declared options or their defaults.
Previously submodules without defs would simply fail for lack of a default,
but since PR #500104 repurposed `emptyValue` as the fallback when no
definitions exist, submodule options without an explicit `default = { }`
(new additions) silently lost their sub-option defaults
(e.g. `requiredFeatures.devnet` in the nixos-test-driver, #511413).
Main change: `emptyValue`: `{ }` -> `{ value = base.config; }`
Additionally, skip `emptyValue`-based default rendering in docs for
types with submodules, because their sub-options are already documented
individually, and forcing evaluation here can break on modules with
invalid or incomplete definitions.
Downstream types that want to use `lib.types.defaultTypeMerge` must include
`wrapped` even though it is deprecated or the internal
`wrappedDeprecationMessage`. This is caused by accessing the
`wrapped` attr in `lib.types.defaultTypeMerge`. The logic should first check
if the attr exists and then if it does check if it is null.
Lists the valid choices in `attrTag` type's `description` field.
Given this description is used in error messages, this serves to make
for somewhat more descriptive errors in the event an option involving
this type turns out not to match.
Signed-off-by: cinereal <cinereal@riseup.net>
This allows individual types to add attributes that would be discarded during normal evaluation.
Some examples:
types.submodule performs a submodule evluation which yields an 'evalModules' result.
It returns '.config' but makes the original result accessible via 'valueMeta' allowing introspection of '.options' and all other kinds of module evaluation results
types.attrsOf returns an attribute set of the nestedType.
It makes each valueMeta available under the corresponding attribute name.