Skip to content

Commit

Permalink
starlark: skip last frame of stack backtrace if built-in (google#319)
Browse files Browse the repository at this point in the history
Instead, the name of the built-in function is append to the
error message ("Error in foo: ...").
  • Loading branch information
adonovan authored Nov 18, 2020
1 parent e292e66 commit a5c0cc4
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 5 deletions.
14 changes: 12 additions & 2 deletions starlark/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,9 @@ func (stack *CallStack) Pop() CallFrame {
// String returns a user-friendly description of the stack.
func (stack CallStack) String() string {
out := new(strings.Builder)
fmt.Fprintf(out, "Traceback (most recent call last):\n")
if len(stack) > 0 {
fmt.Fprintf(out, "Traceback (most recent call last):\n")
}
for _, fr := range stack {
fmt.Fprintf(out, " %s: in %s\n", fr.Pos, fr.Name)
}
Expand Down Expand Up @@ -259,7 +261,15 @@ func (e *EvalError) Error() string { return e.Msg }
// Backtrace returns a user-friendly error message describing the stack
// of calls that led to this error.
func (e *EvalError) Backtrace() string {
return fmt.Sprintf("%sError: %s", e.CallStack, e.Msg)
// If the topmost stack frame is a built-in function,
// remove it from the stack and add print "Error in fn:".
stack := e.CallStack
suffix := ""
if last := len(stack) - 1; last >= 0 && stack[last].Pos.Filename() == builtinFilename {
suffix = " in " + stack[last].Name
stack = stack[:last]
}
return fmt.Sprintf("%sError%s: %s", stack, suffix, e.Msg)
}

func (e *EvalError) Unwrap() error { return e.cause }
Expand Down
7 changes: 4 additions & 3 deletions starlark/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,6 @@ i()
`
thread := new(starlark.Thread)
_, err := starlark.ExecFile(thread, "crash.star", src, nil)
// Compiled code currently has no column information.
const want = `Traceback (most recent call last):
crash.star:6:2: in <toplevel>
crash.star:5:18: in i
Expand All @@ -527,6 +526,9 @@ Error: floored division by zero`

// Additionally, ensure that errors originating in
// Starlark and/or Go each have an accurate frame.
// The topmost frame, if built-in, is not shown,
// but the name of the built-in function is shown
// as "Error in fn: ...".
//
// This program fails in Starlark (f) if x==0,
// or in Go (string.join) if x is non-zero.
Expand All @@ -542,8 +544,7 @@ Error: floored division by zero`,
1: `Traceback (most recent call last):
crash.star:3:2: in <toplevel>
crash.star:2:17: in f
<builtin>: in join
Error: join: in list, want string, got int`,
Error in join: join: in list, want string, got int`,
} {
globals := starlark.StringDict{"i": starlark.MakeInt(i)}
_, err := starlark.ExecFile(thread, "crash.star", src2, globals)
Expand Down

0 comments on commit a5c0cc4

Please sign in to comment.