Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/gopls: panic in deslice when completing unknown type in append #38091

Open
chlunde opened this issue Mar 26, 2020 · 1 comment
Open

x/tools/gopls: panic in deslice when completing unknown type in append #38091

chlunde opened this issue Mar 26, 2020 · 1 comment
Labels
Milestone

Comments

@chlunde
Copy link
Contributor

@chlunde chlunde commented Mar 26, 2020

What did you do?

Type t in struct in an append variadic arg for a slice with a type now yet defined.

package bad

func _() {
       a := unknown
       a = append(a, struct) //@complete(")")
}

What did you expect to see?

Not much

What did you see instead?

Crash

Stack trace
panic: runtime error: invalid memory address or nil pointer dereference                                                                                                                                                                        
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x79e7db]                                                                                                                                                                        

goroutine 10025 [running]:
golang.org/x/tools/internal/lsp/source.deslice(...)
/home/chlunde/opt/gotoolpath/pkg/mod/golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a/internal/lsp/source/util.go:429
golang.org/x/tools/internal/lsp/source.(*completer).builtinArgType(0xc0086f0600, 0xe25040, 0xc000100cd0, 0xc0071bc240, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/home/chlunde/opt/gotoolpath/pkg/mod/golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a/internal/lsp/source/completion_builtin.go:70 +0x3bb
golang.org/x/tools/internal/lsp/source.expectedCandidate.func1(0xc0086f0600, 0xe25040, 0xc000100cd0, 0xc0071bc240, 0xc01032c160)
/home/chlunde/opt/gotoolpath/pkg/mod/golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a/internal/lsp/source/completion.go:1481 +0xd1
golang.org/x/tools/internal/lsp/source.expectedCandidate(0xc0086f0600, 0xc00025b4b0, 0xc010ae66c0, 0xc0000c5300, 0x116f, 0x1300, 0xb9e2e2, 0x52, 0xc0101eb990, 0x6, ...)
/home/chlunde/opt/gotoolpath/pkg/mod/golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a/internal/lsp/source/completion.go:1565 +0x3c7
golang.org/x/tools/internal/lsp/source.Completion(0xe12e60, 0xc010ae66c0, 0xe24f00, 0xc012cc2120, 0xe11560, 0xc012cc20c0, 0x4065a00000000000, 0x4045000000000000, 0x0, 0x0, ...)
/home/chlunde/opt/gotoolpath/pkg/mod/golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a/internal/lsp/source/completion.go:517 +0x9eb
golang.org/x/tools/internal/lsp.(*Server).completion(0xc0002e6680, 0xe12e60, 0xc010b00450, 0xc010536060, 0x0, 0x0, 0xc01032c000)
/home/chlunde/opt/gotoolpath/pkg/mod/golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a/internal/lsp/completion.go:27 +0x6b0
golang.org/x/tools/internal/lsp.(*Server).Completion(0xc0002e6680, 0xe12e60, 0xc010b00450, 0xc010536060, 0xc010536060, 0x0, 0x0)
/home/chlunde/opt/gotoolpath/pkg/mod/golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a/internal/lsp/server_gen.go:24 +0x49
golang.org/x/tools/internal/lsp/protocol.serverHandler.Deliver(0xe2d340, 0xc0002e6680, 0xe12e60, 0xc010b00450, 0xc010a7e1c0, 0xae8c00, 0xe10000)
/home/chlunde/opt/gotoolpath/pkg/mod/golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a/internal/lsp/protocol/tsserver.go:345 +0x2064
golang.org/x/tools/internal/jsonrpc2.(*Conn).Run.func1(0xc0075ec4e0, 0xc010a7e1c0, 0xc0002eaba0, 0xe12e60, 0xc010b00450, 0x0, 0x0, 0xc0071500f0)
/home/chlunde/opt/gotoolpath/pkg/mod/golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a/internal/jsonrpc2/jsonrpc2.go:372 +0x160
created by golang.org/x/tools/internal/jsonrpc2.(*Conn).Run

Build info

gopls v0.3.4
golang.org/x/tools/gopls v0.3.4
    golang.org/x/tools/gopls@v0.3.4 h1:4GC7q/pXQ/tsxHBGVdsMdlB4gCxVC06m/7rIXg1Px4E=
    github.com/BurntSushi/toml@v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
    github.com/sergi/go-diff@v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
    golang.org/x/mod@v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
    golang.org/x/sync@v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
    golang.org/x/tools@v0.0.0-20200316194252-fafb6e2e8a4a h1:hKrQy/q8/Xivoqgw6nGiz1jqpn1WGBLDcWLZwW0983E=
    golang.org/x/xerrors@v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
    honnef.co/go/tools@v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
    mvdan.cc/xurls/v2@v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=

Hack/patch

Not sure if this is the right approach ¯\(ツ)

diff --git a/internal/lsp/testdata/lsp/primarymod/bad/bad2.go b/internal/lsp/testdata/lsp/primarymod/bad/bad2.go
new file mode 100644
index 00000000..acce3e45
--- /dev/null
+++ b/internal/lsp/testdata/lsp/primarymod/bad/bad2.go
@@ -0,0 +1,6 @@
+package bad
+
+func _() {
+       a := unknown
+       a = append(a, struct) //@complete(")")
+}
diff --git a/internal/lsp/testdata/lsp/summary.txt.golden b/internal/lsp/testdata/lsp/summary.txt.golden
index c4e7d68d..ece318e5 100644
--- a/internal/lsp/testdata/lsp/summary.txt.golden
+++ b/internal/lsp/testdata/lsp/summary.txt.golden
@@ -1,6 +1,6 @@
 -- summary --
 CodeLensCount = 2
-CompletionsCount = 237
+CompletionsCount = 238
 CompletionSnippetCount = 75
 UnimportedCompletionsCount = 11
 DeepCompletionsCount = 5
diff --git a/internal/lsp/source/completion_builtin.go b/internal/lsp/source/completion_builtin.go
index d65eb8f4..26c553f0 100644
--- a/internal/lsp/source/completion_builtin.go
+++ b/internal/lsp/source/completion_builtin.go
@@ -64,7 +64,7 @@ func (c *completer) builtinArgType(obj types.Object, call *ast.CallExpr, parentI
                // Check if we are completing the variadic append() param.
                if exprIdx == 1 && len(call.Args) <= 2 {
                        inf.variadicType = deslice(inf.objType)
-               } else if exprIdx > 0 {
+               } else if exprIdx > 0 && inf.objType != nil {
                        // If we are completing an individual element of the variadic
                        // param, "deslice" the expected type.
                        inf.objType = deslice(inf.objType)
@gopherbot gopherbot added this to the Unreleased milestone Mar 26, 2020
@stamblerre

This comment has been minimized.

Copy link
Contributor

@stamblerre stamblerre commented Mar 26, 2020

Thanks for the report! The patch you proposed above sounds reasonable to me - please send us a PR if you're interested in contributing :)

/cc @muirdm

@stamblerre stamblerre modified the milestones: Unreleased, gopls/v0.4.0 Mar 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.