[Nix-dev] [PATCH] nix2/debug

Marc Weber marco-oweber at gmx.de
Mon Mar 14 02:25:35 CET 2011


patch hepling debugging nix code failures.

If you get got X but Y expected this patch will make nix print what X exactly is using XML dump.

Signed-off-by: Marc Weber <marco-oweber at gmx.de>
---
 src/libexpr/eval.cc                    |   40 +++++++++++++++++++++----------
 src/libexpr/eval.hh                    |    2 +
 src/libmain/shared.cc                  |    3 ++
 src/libstore/globals.cc                |    1 +
 src/libstore/globals.hh                |    6 ++++-
 src/nix-instantiate/nix-instantiate.cc |    3 ++
 6 files changed, 41 insertions(+), 14 deletions(-)

diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 949f45e..ce710ba 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -5,6 +5,7 @@
 #include "store-api.hh"
 #include "derivations.hh"
 #include "globals.hh"
+#include "value-to-xml.hh"
 
 #include <cstring>
 #include <unistd.h>
@@ -202,6 +203,18 @@ void EvalState::addConstant(const string & name, Value & v)
 }
 
 
+string EvalState::showTypeOrXml(Value &v){
+    if (xmldebugCorcionFailure){
+        // make running this code intsead optional
+        std::ostringstream out;
+        PathSet context;
+        printValueAsXML(*this, true, false, v, out, context);
+        return out.str(); // don't know whether this is safe !
+    } else {
+        return showType(v);
+    }
+}
+
 void EvalState::addPrimOp(const string & name,
     unsigned int arity, PrimOpFun primOp)
 {
@@ -490,7 +503,7 @@ bool EvalState::evalBool(Env & env, Expr * e)
     Value v;
     eval(env, e, v);
     if (v.type != tBool)
-        throwTypeError("value is %1% while a Boolean was expected", showType(v));
+        throwTypeError("value is %1% while a Boolean was expected", showTypeOrXml(v));
     return v.boolean;
 }
 
@@ -499,7 +512,7 @@ void EvalState::evalAttrs(Env & env, Expr * e, Value & v)
 {
     eval(env, e, v);
     if (v.type != tAttrs)
-        throwTypeError("value is %1% while an attribute set was expected", showType(v));
+        throwTypeError("value is %1% while an attribute set was expected", showTypeOrXml(v));
 }
 
 
@@ -721,7 +734,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v)
     
     if (fun.type != tLambda)
         throwTypeError("attempt to call something which is neither a function nor a primop (built-in operation) but %1%",
-            showType(fun));
+            showTypeOrXml(fun));
 
     unsigned int size =
         (fun.lambda.fun->arg.empty() ? 0 : 1) +
@@ -989,7 +1002,7 @@ int EvalState::forceInt(Value & v)
 {
     forceValue(v);
     if (v.type != tInt)
-        throwTypeError("value is %1% while an integer was expected", showType(v));
+        throwTypeError("value is %1% while an integer was expected", showTypeOrXml(v));
     return v.integer;
 }
 
@@ -998,7 +1011,7 @@ bool EvalState::forceBool(Value & v)
 {
     forceValue(v);
     if (v.type != tBool)
-        throwTypeError("value is %1% while a Boolean was expected", showType(v));
+        throwTypeError("value is %1% while a Boolean was expected", showTypeOrXml(v));
     return v.boolean;
 }
 
@@ -1007,15 +1020,16 @@ void EvalState::forceAttrs(Value & v)
 {
     forceValue(v);
     if (v.type != tAttrs)
-        throwTypeError("value is %1% while an attribute set was expected", showType(v));
+        throwTypeError("value is %1% while an attribute set was expected", showTypeOrXml(v));
 }
 
 
 void EvalState::forceList(Value & v)
 {
     forceValue(v);
-    if (v.type != tList)
-        throwTypeError("value is %1% while a list was expected", showType(v));
+    if (v.type != tList){
+        throwTypeError("value is %1% while a list was expected", showTypeOrXml(v));
+    }
 }
 
 
@@ -1023,7 +1037,7 @@ void EvalState::forceFunction(Value & v)
 {
     forceValue(v);
     if (v.type != tLambda && v.type != tPrimOp && v.type != tPrimOpApp)
-        throwTypeError("value is %1% while a function was expected", showType(v));
+        throwTypeError("value is %1% while a function was expected", showTypeOrXml(v));
 }
 
 
@@ -1031,7 +1045,7 @@ string EvalState::forceString(Value & v)
 {
     forceValue(v);
     if (v.type != tString)
-        throwTypeError("value is %1% while a string was expected", showType(v));
+        throwTypeError("value is %1% while a string was expected", showTypeOrXml(v));
     return string(v.string.s);
 }
 
@@ -1109,7 +1123,7 @@ string EvalState::coerceToString(Value & v, PathSet & context,
     if (v.type == tAttrs) {
         Bindings::iterator i = v.attrs->find(sOutPath);
         if (i == v.attrs->end())
-            throwTypeError("cannot coerce an attribute set (except a derivation) to a string");
+            throwTypeError("cannot coerce an attribute set: %1% (except a derivation) to a string", showTypeOrXml(v));
         return coerceToString(*i->value, context, coerceMore, copyToStore);
     }
 
@@ -1136,7 +1150,7 @@ string EvalState::coerceToString(Value & v, PathSet & context,
         }
     }
     
-    throwTypeError("cannot coerce %1% to a string", showType(v));
+    throwTypeError("cannot coerce %1% to a string", showTypeOrXml(v));
 }
 
 
@@ -1210,7 +1224,7 @@ bool EvalState::eqValues(Value & v1, Value & v2)
             return false;
 
         default:
-            throwEvalError("cannot compare %1% with %2%", showType(v1), showType(v2));
+            throwEvalError("cannot compare %1% with %2%", showTypeOrXml(v1), showTypeOrXml(v2));
     }
 }
 
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 7453ac1..52bda5b 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -294,6 +294,8 @@ private:
     void addPrimOp(const string & name,
         unsigned int arity, PrimOpFun primOp);
 
+    string showTypeOrXml(Value &v);
+
     Value * lookupVar(Env * env, const VarRef & var);
     
     friend class ExprVar;
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index 3110c94..41c1463 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -241,6 +241,9 @@ static void initAndRun(int argc, char * * argv)
             useBuildHook = false;
         else if (arg == "--show-trace")
             showTrace = true;
+        else if (arg == "--xml-debug-coercion-failure") {
+            xmldebugCorcionFailure = true;
+        }
         else if (arg == "--option") {
             ++i; if (i == args.end()) throw UsageError("`--option' requires two arguments");
             string name = *i;
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 7069d10..aa90d46 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -24,6 +24,7 @@ Verbosity buildVerbosity = lvlError;
 unsigned int maxBuildJobs = 1;
 unsigned int buildCores = 1;
 bool readOnlyMode = false;
+bool xmldebugCorcionFailure = false;
 string thisSystem = "unset";
 time_t maxSilentTime = 0;
 Paths substituters;
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index a74a741..f5893bb 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -110,7 +110,11 @@ void overrideSetting(const string & name, const Strings & value);
 
 void reloadSettings();
 
-    
+/* if set to true this prints the type which nix tried to coerce to a non matching type
+ * printing the xml can lead to infinite recursions etc.. So this is for
+ * debugging your Nix code only
+ */
+extern bool xmldebugCorcionFailure;
 }
 
 
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index 3d3b643..9e2652c 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -97,6 +97,9 @@ void run(Strings args)
             readOnlyMode = true;
             evalOnly = true;
         }
+        else if (arg == "--xml-debug-coercion-failure") {
+            xmldebugCorcionFailure = true;
+        }
         else if (arg == "--parse-only") {
             readOnlyMode = true;
             parseOnly = evalOnly = true;
-- 
1.6.6.2




More information about the nix-dev mailing list