diff --git a/lib/trivial.nix b/lib/trivial.nix
index 5d4fad8266bc9..46cd35f883f30 100644
--- a/lib/trivial.nix
+++ b/lib/trivial.nix
@@ -442,6 +442,67 @@ rec {
then f.__functionArgs or (lib.functionArgs (f.__functor f))
else builtins.functionArgs f;
+ getFunction = f:
+ if builtins.isFunction f then f
+ else if f ? __functor
+ then getFunction (f.__functor f)
+ else throw "getFunction: Not a function";
+
+ /*
+ functionInfo builtins.add ->
+ {
+ type = "builtin";
+ }
+
+ functionInfo (arg: arg + 1) ->
+ {
+ type = "argument";
+ argumentName = "arg";
+ }
+
+ functionInfo (arg@{ a }: a + 1) ->
+ {
+ type = "attributes";
+ argumentName = "arg";
+ attributes = { a = false; };
+ ellipsis = false;
+ }
+ functionInfo ({ a ? 0, ...}: a + 1) ->
+ {
+ type = "attributes";
+ argumentName = null;
+ attributes = { a = true; };
+ ellipsis = true;
+ }
+ */
+ functionInfo = f:
+ let
+ function = getFunction f;
+ xmlString = builtins.toXML function;
+ builtinString = "\n\n \n\n";
+ argumentRegex = "<\\?xml version='1.0' encoding='utf-8'\\?>\n\n \n \n \n\n";
+ argumentMatch = builtins.match argumentRegex xmlString;
+ attributesRegex = "<\\?xml version='1.0' encoding='utf-8'\\?>\n\n \n .*\n \n \n\n";
+ attributesMatch = builtins.match attributesRegex xmlString;
+ in
+ if builtinString == xmlString then {
+ type = "builtin";
+ }
+ else if argumentMatch != null then {
+ type = "argument";
+ argumentName = builtins.elemAt argumentMatch 0;
+ }
+ else if attributesMatch != null then {
+ type = "attributes";
+ argumentName =
+ if builtins.elemAt attributesMatch 1 != null
+ then builtins.elemAt attributesMatch 2
+ else null;
+ ellipsis = builtins.elemAt attributesMatch 0 != null;
+ attributes = builtins.functionArgs function;
+ }
+ else throw "functionInfo: Cannot parse builtins.toXML output (this is a bug): ${xmlString}";
+
/* Check whether something is a function or something
annotated with function args.
*/