commit 3c2368fda0e3a2a393819d36171a5dcee92fc553 Author: Marc Weber Date: Fri Aug 24 11:53:07 2012 +0200 experimental/debug-coercions-as-xml We're all pretty helpless seeing messages like: value is an attribute set while a list was expected This patch add sthe flag --xml-debug-coercion-failure making nix output the xml representation of the attribute set - which of course may fail eg if infinite recursions are used. However its more often useful than failing. Signed-off-by: Marc Weber diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index 57a9e4c..d114e64 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -42,7 +42,7 @@ inline 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)); } @@ -50,7 +50,7 @@ inline void EvalState::forceList(Value & v) { forceValue(v); if (v.type != tList) - throwTypeError("value is %1% while a list was expected", showType(v)); + throwTypeError("value is %1% while a list was expected", showTypeOrXml(v)); } } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index cf7c62a..55f823d 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -4,6 +4,7 @@ #include "store-api.hh" #include "derivations.hh" #include "globals.hh" +#include "value-to-xml.hh" #include "eval-inline.hh" #include @@ -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) { @@ -448,7 +461,7 @@ inline bool EvalState::evalBool(Env & env, Expr * e) Value v; e->eval(*this, env, 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; } @@ -457,7 +470,7 @@ inline void EvalState::evalAttrs(Env & env, Expr * e, Value & v) { e->eval(*this, env, 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)); } @@ -717,7 +730,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) + @@ -966,7 +979,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; } @@ -975,7 +988,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; } @@ -984,7 +997,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)); } @@ -992,7 +1005,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); } @@ -1073,7 +1086,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); } @@ -1100,7 +1113,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)); } @@ -1186,7 +1199,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 5103ae8..b997afa 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -201,6 +201,8 @@ private: void addPrimOp(const string & name, unsigned int arity, PrimOpFun primOp); + string showTypeOrXml(Value &v); + inline Value * lookupVar(Env * env, const VarRef & var); friend class ExprVar; diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index d398165..0523633 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -198,6 +198,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 5c22f14..4baf982 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -26,6 +26,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; time_t buildTimeout = 0; diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 1c0877a..967c1db 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -113,7 +113,13 @@ void overrideSetting(const string & name, const Strings & value); void reloadSettings(); -void setDefaultsFromEnvironment(); +/* 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; + +void setDefaultsFromEnvironment(); } diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index d86c9fc..915fcca 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;