libexpr: add set-to-string error frame
this is much more useful than a frame pointing to the set but claiming it as a function being called. if the function is actually at fault we will now point to its attribute, although the position may be slightly wrong if __toString was defined from set updates or builtin functions. Change-Id: Ib3eb237a276d94426d9c6fc0e26eea72382d34a2
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
---
|
||||
synopsis: 'Implicit `__toString` now have stack trace entries'
|
||||
issues: []
|
||||
cls: [3055]
|
||||
category: Improvements
|
||||
credits: [horrors]
|
||||
---
|
||||
|
||||
Coercion of attribute sets to strings via their `__toString` attribute now produce stack
|
||||
frames pointing to the coercion site and the attribute definition. This makes locating a
|
||||
coercion function error easier as the fault location is now more likely to be presented.
|
||||
|
||||
Previously:
|
||||
```
|
||||
nix-repl> builtins.substring 1 1 "${{ __toString = self: throw ''bar''; }}"
|
||||
error:
|
||||
… while calling the 'substring' builtin
|
||||
at «string»:1:1:
|
||||
1| builtins.substring 1 1 "${{ __toString = self: throw ''bar''; }}"
|
||||
| ^
|
||||
|
||||
… caused by explicit throw
|
||||
at «string»:1:48:
|
||||
1| builtins.substring 1 1 "${{ __toString = self: throw ''bar''; }}"
|
||||
| ^
|
||||
|
||||
error: bar
|
||||
```
|
||||
|
||||
Now:
|
||||
```
|
||||
nix-repl> builtins.substring 1 1 "${{ __toString = self: throw ''bar''; }}"
|
||||
error:
|
||||
… while calling the 'substring' builtin
|
||||
at «string»:1:1:
|
||||
1| builtins.substring 1 1 "${{ __toString = self: throw ''bar''; }}"
|
||||
| ^
|
||||
|
||||
… while converting a set to string
|
||||
at «string»:1:25:
|
||||
1| builtins.substring 1 1 "${{ __toString = self: throw ''bar''; }}"
|
||||
| ^
|
||||
|
||||
… from call site
|
||||
at «string»:1:29:
|
||||
1| builtins.substring 1 1 "${{ __toString = self: throw ''bar''; }}"
|
||||
| ^
|
||||
|
||||
… while calling '__toString'
|
||||
at «string»:1:42:
|
||||
1| builtins.substring 1 1 "${{ __toString = self: throw ''bar''; }}"
|
||||
| ^
|
||||
|
||||
… caused by explicit throw
|
||||
at «string»:1:48:
|
||||
1| builtins.substring 1 1 "${{ __toString = self: throw ''bar''; }}"
|
||||
| ^
|
||||
|
||||
error: bar
|
||||
```
|
||||
+9
-4
@@ -2309,10 +2309,15 @@ std::optional<std::string> EvalState::tryAttrsToString(const PosIdx pos, Value &
|
||||
auto i = v.attrs->find(ctx.s.toString);
|
||||
if (i != v.attrs->end()) {
|
||||
Value v1;
|
||||
callFunction(*i->value, v, v1, pos);
|
||||
return coerceToString(pos, v1, context,
|
||||
"while evaluating the result of the `__toString` attribute",
|
||||
coerceMore, copyToStore).toOwned();
|
||||
try {
|
||||
callFunction(*i->value, v, v1, i->pos);
|
||||
return coerceToString(pos, v1, context,
|
||||
"while evaluating the result of the `__toString` attribute",
|
||||
coerceMore, copyToStore).toOwned();
|
||||
} catch (EvalError & e) {
|
||||
e.addTrace(ctx.positions[pos], "while converting a set to string");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
error:
|
||||
… while calling the 'toString' builtin
|
||||
at /pwd/lang/eval-fail-toString.nix:1:1:
|
||||
1| toString { __toString = 1; }
|
||||
| ^
|
||||
2|
|
||||
|
||||
… while converting a set to string
|
||||
|
||||
error: attempt to call something which is not a function but an integer: 1
|
||||
at /pwd/lang/eval-fail-toString.nix:1:12:
|
||||
1| toString { __toString = 1; }
|
||||
| ^
|
||||
2|
|
||||
@@ -0,0 +1 @@
|
||||
toString { __toString = 1; }
|
||||
Reference in New Issue
Block a user