Output line number on infinite recursion
This commit is contained in:
		
							parent
							
								
									76cc8e97a2
								
							
						
					
					
						commit
						75837651f1
					
				
					 4 changed files with 17 additions and 13 deletions
				
			
		|  | @ -1,15 +1,16 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
|  | #include "shared.hh" | ||||||
| 
 | 
 | ||||||
| #define LocalNoInline(f) static f __attribute__((noinline)); f | #define LocalNoInline(f) static f __attribute__((noinline)); f | ||||||
| #define LocalNoInlineNoReturn(f) static f __attribute__((noinline, noreturn)); f | #define LocalNoInlineNoReturn(f) static f __attribute__((noinline, noreturn)); f | ||||||
| 
 | 
 | ||||||
| namespace nix { | namespace nix { | ||||||
| 
 | 
 | ||||||
| LocalNoInlineNoReturn(void throwEvalError(const char * s)) | LocalNoInlineNoReturn(void throwEvalError(const FormatOrString & fs)) | ||||||
| { | { | ||||||
|     throw EvalError(s); |     throw EvalError(fs); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v)) | LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v)) | ||||||
|  | @ -24,7 +25,7 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v, const | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void EvalState::forceValue(Value & v) | void EvalState::forceValue(Value & v, const Pos & pos) | ||||||
| { | { | ||||||
|     if (v.type == tThunk) { |     if (v.type == tThunk) { | ||||||
|         Env * env = v.thunk.env; |         Env * env = v.thunk.env; | ||||||
|  | @ -43,7 +44,7 @@ void EvalState::forceValue(Value & v) | ||||||
|     else if (v.type == tApp) |     else if (v.type == tApp) | ||||||
|         callFunction(*v.app.left, *v.app.right, v, noPos); |         callFunction(*v.app.left, *v.app.right, v, noPos); | ||||||
|     else if (v.type == tBlackhole) |     else if (v.type == tBlackhole) | ||||||
|         throwEvalError("infinite recursion encountered"); |         throwEvalError(format("infinite recursion encountered, at %1%") % pos); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -746,7 +746,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) | ||||||
|     for (auto & i : dynamicAttrs) { |     for (auto & i : dynamicAttrs) { | ||||||
|         Value nameVal; |         Value nameVal; | ||||||
|         i.nameExpr->eval(state, *dynamicEnv, nameVal); |         i.nameExpr->eval(state, *dynamicEnv, nameVal); | ||||||
|         state.forceValue(nameVal); |         state.forceValue(nameVal, i.pos); | ||||||
|         if (nameVal.type == tNull) |         if (nameVal.type == tNull) | ||||||
|             continue; |             continue; | ||||||
|         state.forceStringNoCtx(nameVal); |         state.forceStringNoCtx(nameVal); | ||||||
|  | @ -792,7 +792,7 @@ void ExprList::eval(EvalState & state, Env & env, Value & v) | ||||||
| void ExprVar::eval(EvalState & state, Env & env, Value & v) | void ExprVar::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     Value * v2 = state.lookupVar(&env, *this, false); |     Value * v2 = state.lookupVar(&env, *this, false); | ||||||
|     state.forceValue(*v2); |     state.forceValue(*v2, pos); | ||||||
|     v = *v2; |     v = *v2; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -831,7 +831,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) | ||||||
|             Bindings::iterator j; |             Bindings::iterator j; | ||||||
|             Symbol name = getName(i, state, env); |             Symbol name = getName(i, state, env); | ||||||
|             if (def) { |             if (def) { | ||||||
|                 state.forceValue(*vAttrs); |                 state.forceValue(*vAttrs, pos); | ||||||
|                 if (vAttrs->type != tAttrs || |                 if (vAttrs->type != tAttrs || | ||||||
|                     (j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) |                     (j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) | ||||||
|                 { |                 { | ||||||
|  | @ -848,7 +848,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) | ||||||
|             if (state.countCalls && pos2) state.attrSelects[*pos2]++; |             if (state.countCalls && pos2) state.attrSelects[*pos2]++; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         state.forceValue(*vAttrs); |         state.forceValue(*vAttrs, ( pos2 != NULL ? *pos2 : this->pos ) ); | ||||||
| 
 | 
 | ||||||
|     } catch (Error & e) { |     } catch (Error & e) { | ||||||
|         if (pos2 && pos2->file != state.sDerivationNix) |         if (pos2 && pos2->file != state.sDerivationNix) | ||||||
|  | @ -950,10 +950,10 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po | ||||||
|     if (fun.type == tAttrs) { |     if (fun.type == tAttrs) { | ||||||
|       auto found = fun.attrs->find(sFunctor); |       auto found = fun.attrs->find(sFunctor); | ||||||
|       if (found != fun.attrs->end()) { |       if (found != fun.attrs->end()) { | ||||||
|         forceValue(*found->value); |         forceValue(*found->value, pos); | ||||||
|         Value * v2 = allocValue(); |         Value * v2 = allocValue(); | ||||||
|         callFunction(*found->value, fun, *v2, pos); |         callFunction(*found->value, fun, *v2, pos); | ||||||
|         forceValue(*v2); |         forceValue(*v2, pos); | ||||||
|         return callFunction(*v2, arg, v, pos); |         return callFunction(*v2, arg, v, pos); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  | @ -1280,7 +1280,7 @@ void EvalState::forceValueDeep(Value & v) | ||||||
| 
 | 
 | ||||||
| NixInt EvalState::forceInt(Value & v, const Pos & pos) | NixInt EvalState::forceInt(Value & v, const Pos & pos) | ||||||
| { | { | ||||||
|     forceValue(v); |     forceValue(v, pos); | ||||||
|     if (v.type != tInt) |     if (v.type != tInt) | ||||||
|         throwTypeError("value is %1% while an integer was expected, at %2%", v, pos); |         throwTypeError("value is %1% while an integer was expected, at %2%", v, pos); | ||||||
|     return v.integer; |     return v.integer; | ||||||
|  | @ -1306,7 +1306,7 @@ void EvalState::forceFunction(Value & v, const Pos & pos) | ||||||
| 
 | 
 | ||||||
| string EvalState::forceString(Value & v, const Pos & pos) | string EvalState::forceString(Value & v, const Pos & pos) | ||||||
| { | { | ||||||
|     forceValue(v); |     forceValue(v, pos); | ||||||
|     if (v.type != tString) { |     if (v.type != tString) { | ||||||
|         if (pos) |         if (pos) | ||||||
|             throwTypeError("value is %1% while a string was expected, at %2%", v, pos); |             throwTypeError("value is %1% while a string was expected, at %2%", v, pos); | ||||||
|  |  | ||||||
|  | @ -136,7 +136,7 @@ public: | ||||||
|        of the evaluation of the thunk.  If `v' is a delayed function |        of the evaluation of the thunk.  If `v' is a delayed function | ||||||
|        application, call the function and overwrite `v' with the |        application, call the function and overwrite `v' with the | ||||||
|        result.  Otherwise, this is a no-op. */ |        result.  Otherwise, this is a no-op. */ | ||||||
|     inline void forceValue(Value & v); |     inline void forceValue(Value & v, const Pos & pos = noPos); | ||||||
| 
 | 
 | ||||||
|     /* Force a value, then recursively force list elements and
 |     /* Force a value, then recursively force list elements and
 | ||||||
|        attributes. */ |        attributes. */ | ||||||
|  |  | ||||||
|  | @ -14,3 +14,6 @@ nix-env --version | grep "$version" | ||||||
| # Usage errors. | # Usage errors. | ||||||
| nix-env --foo 2>&1 | grep "no operation" | nix-env --foo 2>&1 | grep "no operation" | ||||||
| nix-env -q --foo 2>&1 | grep "unknown flag" | nix-env -q --foo 2>&1 | grep "unknown flag" | ||||||
|  | 
 | ||||||
|  | # Eval Errors. | ||||||
|  | nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 | grep "infinite recursion encountered, at (string):1:15$" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue