google / go-jsonnet

Apache License 2.0
1.61k stars 232 forks source link

Linter panic involving a circular dependency? #591

Open wattdave opened 2 years ago

wattdave commented 2 years ago

Here's a reduced example, using jsonnet-lint from 0.18.0:

# a.libsonnet
local b = import './b.libsonnet';

local p = {
  s:: [],

  c: b.callThis(self.s),
};

// Exposed for public use.
{
  p:: p,
}
# b.libsonnet
local callThis(fromOther) = fromOther;

// Exposed for public use.
{
  callThis:: callThis,
}

Linter behavior:

 jsonnet-lint a.libsonnet b.libsonnet                                                                                      [git:master] ✖  
panic: Bug - placeholder for a dependent node cannot be noType

goroutine 1 [running]:
github.com/google/go-jsonnet/linter/internal/types.(*typeGraph).getExprPlaceholder(...)
    /private/tmp/go-jsonnet-20211222-86046-dhqer5/go-jsonnet-0.18.0/linter/internal/types/build_graph.go:26
github.com/google/go-jsonnet/linter/internal/types.calcTP({0x11fe8b8, 0xc0001da180}, 0x0, 0xc0001fb320)
    /private/tmp/go-jsonnet-20211222-86046-dhqer5/go-jsonnet-0.18.0/linter/internal/types/build_graph.go:217 +0x280e
github.com/google/go-jsonnet/linter/internal/types.prepareTPWithPlaceholder({0x11fe8b8, 0xc0001da180}, 0x0, 0xc0001fb320, 0x79)
    /private/tmp/go-jsonnet-20211222-86046-dhqer5/go-jsonnet-0.18.0/linter/internal/types/build_graph.go:86 +0x1ae
github.com/google/go-jsonnet/linter/internal/types.prepareTPWithPlaceholder({0x11feaf8, 0xc0001b0460}, 0x7ff7bfeff875, 0xc0001fb320, 0x77)
    /private/tmp/go-jsonnet-20211222-86046-dhqer5/go-jsonnet-0.18.0/linter/internal/types/build_graph.go:62 +0x5ba
github.com/google/go-jsonnet/linter/internal/types.(*typeGraph).addRoots(0xc0001fb320, 0x11fe8b8, 0xd0)
    /private/tmp/go-jsonnet-20211222-86046-dhqer5/go-jsonnet-0.18.0/linter/internal/types/build_graph.go:96 +0x31a
github.com/google/go-jsonnet/linter/internal/types.Check({0x11feaf8, 0xc0001b0460}, 0x11bbb03, 0x4, 0xc0001c4348, 0x0)
    /private/tmp/go-jsonnet-20211222-86046-dhqer5/go-jsonnet-0.18.0/linter/internal/types/check.go:138 +0xc7
github.com/google/go-jsonnet/linter.lint(0xc0001821e0, {0xc00018e300, 0x2, 0x10a0c54}, 0xc0001a20c0)
    /private/tmp/go-jsonnet-20211222-86046-dhqer5/go-jsonnet-0.18.0/linter/linter.go:87 +0x6d4
github.com/google/go-jsonnet/linter.LintSnippet(0x119fcc0, {0x11fa4e0, 0xc000180010}, {0xc00018e200, 0x2, 0x12fe080})
    /private/tmp/go-jsonnet-20211222-86046-dhqer5/go-jsonnet-0.18.0/linter/linter.go:152 +0x9d
main.main()
    /private/tmp/go-jsonnet-20211222-86046-dhqer5/go-jsonnet-0.18.0/cmd/jsonnet-lint/cmd.go:183 +0x906
dcopso commented 1 year ago

I can reproduce this with a slightly simpler input (no private fields, helper has no parameters).

$ more repro.jsonnet 
local helpers = import 'helpers.libsonnet';

{
  o: 'hello',
} + helpers.otherfile()

$ more helpers.libsonnet 
{
  otherfile(): {
    prefix: 'o:' + self.o,
  },
}

$ jsonnet repro.jsonnet 
{
   "o": "hello",
   "prefix": "o:hello"
}

# linting single file is fine
$ jsonnet-lint repro.jsonnet
$ jsonnet-lint helpers.libsonnet

# linting both files fails (filename order does not matter)
$ jsonnet-lint repro.jsonnet helpers.libsonnet 
panic: Bug - placeholder for a dependent node cannot be noType

goroutine 1 [running]:
github.com/google/go-jsonnet/linter/internal/types.(*typeGraph).getExprPlaceholder(...)
    /home/ubuntu/go/pkg/mod/github.com/google/go-jsonnet@v0.20.0/linter/internal/types/build_graph.go:26
github.com/google/go-jsonnet/linter/internal/types.calcTP({0x66eb98?, 0xc000136180?}, 0x4169cb?, 0xc00014a7e0)
    /home/ubuntu/go/pkg/mod/github.com/google/go-jsonnet@v0.20.0/linter/internal/types/build_graph.go:217 +0x2db8
github.com/google/go-jsonnet/linter/internal/types.prepareTPWithPlaceholder({0x66eb98, 0xc000136180?}, 0x4c?, 0xc00014a7e0, 0x82)
    /home/ubuntu/go/pkg/mod/github.com/google/go-jsonnet@v0.20.0/linter/internal/types/build_graph.go:86 +0x1ae
github.com/google/go-jsonnet/linter/internal/types.prepareTPWithPlaceholder({0x66ee20, 0xc00011e3c0?}, 0x7ffe79b42e89?, 0xc00014a7e0, 0x81)
    /home/ubuntu/go/pkg/mod/github.com/google/go-jsonnet@v0.20.0/linter/internal/types/build_graph.go:62 +0x59d
github.com/google/go-jsonnet/linter/internal/types.(*typeGraph).addRoots(0xc00014a7e0, 0x40c9a5?, 0x0?)
    /home/ubuntu/go/pkg/mod/github.com/google/go-jsonnet@v0.20.0/linter/internal/types/build_graph.go:96 +0x313
github.com/google/go-jsonnet/linter/internal/types.Check({0x66ee20, 0xc00011e3c0}, 0x5e38a9?, 0x4?, 0x1300?, 0x7fd36e1a8328?)
    /home/ubuntu/go/pkg/mod/github.com/google/go-jsonnet@v0.20.0/linter/internal/types/check.go:138 +0xac
github.com/google/go-jsonnet/linter.lint(0xc000072180, {0xc00002c340, 0x2, 0x49fcf4?}, 0xc000020100?)
    /home/ubuntu/go/pkg/mod/github.com/google/go-jsonnet@v0.20.0/linter/linter.go:87 +0x6b4
github.com/google/go-jsonnet/linter.LintSnippet(0x5c7440?, {0x66de38?, 0xc00000e020?}, {0xc00002c280?, 0x2?, 0x0?})
    /home/ubuntu/go/pkg/mod/github.com/google/go-jsonnet@v0.20.0/linter/linter.go:158 +0xa5
main.main()
    /home/ubuntu/go/pkg/mod/github.com/google/go-jsonnet@v0.20.0/cmd/jsonnet-lint/cmd.go:183 +0x845

Binary installed with:

go install github.com/google/go-jsonnet/cmd/jsonnet-lint@latest

Versions:

$ go version
go version go1.18.3 linux/amd64
$ jsonnet-lint --version
Jsonnet linter v0.20.0
kingindanord commented 9 months ago

I'm experiencing a similar problem. Additionally, the error message doesn't specify which files are causing the issue. As a result, I had to manually run the lint process on various file combinations to find out.

You can actually reproduce this error by applying jsonnet-lint on the example in the "imports" section of jsonnet tutorial https://jsonnet.org/learning/tutorial.html

augmentmoogi commented 9 months ago

Any update on this? Experiencing this as well.

For me - I am running the linter through pre-commit.

If I run pre-commit run --all-files jsonnet-lint I see the error, but if I run on individual files - I don't see a problem

for file in `find . -name '*.jsonnet'`
do
    echo $file
    pre-commit run jsonnet-lint --files $file
done
consideRatio commented 6 months ago

@augmentmoogi finding that this happens when multiple files are passed seems like a good indication of what goes wrong - running files individually worked for me as well while running multiple at the same time led to this.

consideRatio commented 6 months ago
Problems found!
panic: Bug - placeholder for a dependent node cannot be noType

Stacktrace from entrypoint into deeper and deeper function calls.

https://github.com/google/go-jsonnet/blob/fed90cd9cd733a87f9fb27cfb32a3e08a7695603/cmd/jsonnet-lint/cmd.go#L183

https://github.com/google/go-jsonnet/blob/fed90cd9cd733a87f9fb27cfb32a3e08a7695603/linter/linter.go#L140-L141

https://github.com/google/go-jsonnet/blob/fed90cd9cd733a87f9fb27cfb32a3e08a7695603/linter/linter.go#L87

https://github.com/google/go-jsonnet/blob/fed90cd9cd733a87f9fb27cfb32a3e08a7695603/linter/internal/types/check.go#L138

https://github.com/google/go-jsonnet/blob/fed90cd9cd733a87f9fb27cfb32a3e08a7695603/linter/internal/types/build_graph.go#L89-L98

Remaining calls are all within the build_graph file, and they go like:

prepareTPWithPlaceholder -> prepareTP -> prepareTPWithPlaceholder -> calcTP -> getExprPlaceholder, and it ends there:

https://github.com/google/go-jsonnet/blob/fed90cd9cd733a87f9fb27cfb32a3e08a7695603/linter/internal/types/build_graph.go#L22-L32

vergenzt commented 2 months ago

FYI I'm working around this by using GNU parallel to run jsonnet-lint on each file separately, with the following config:

- repo: https://github.com/google/go-jsonnet
  rev: v0.20.0
  hooks:
  - id: jsonnet-format
  - id: jsonnet-lint

    # work around https://github.com/google/go-jsonnet/issues/591
    entry: 'parallel jsonnet-lint :::'

I imagine you could do something similar with xargs, e.g. entry: 'xargs -n1 jsonnet-lint', but I haven't tested that.