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

Debugger shows only 1 entry in a map whose keys are structs #1042

Closed
Gelio opened this issue Dec 17, 2020 · 9 comments
Closed

Debugger shows only 1 entry in a map whose keys are structs #1042

Gelio opened this issue Dec 17, 2020 · 9 comments
Assignees
Labels
Debug Issues related to the debugging functionality of the extension. FrozenDueToAge

Comments

@Gelio
Copy link

Gelio commented Dec 17, 2020

What version of Go, VS Code & VS Code Go extension are you using?

  • Run go version to get version of Go
    • go version go1.15.6 linux/amd64
  • Run gopls -v version to get version of Gopls if you are using the language server.
    • golang.org/x/tools/gopls v0.6.0
  • Run code -v or code-insiders -v to get version of VS Code or VS Code Insiders
    • 1.53.0-insider d8a7c31aba3af66354565678e83cce7770daf146 x64
  • Check your installed extensions to get the version of the VS Code Go extension
    • 0.19.1
  • Run go env to get the go development environment details
    •   GO111MODULE=""
        GOARCH="amd64"
        GOBIN=""
        GOCACHE="/home/voreny/.cache/go-build"
        GOENV="/home/voreny/.config/go/env"
        GOEXE=""
        GOFLAGS=""
        GOHOSTARCH="amd64"
        GOHOSTOS="linux"
        GOINSECURE=""
        GOMODCACHE="/home/voreny/go/pkg/mod"
        GONOPROXY=""
        GONOSUMDB=""
        GOOS="linux"
        GOPATH="/home/voreny/go"
        GOPRIVATE=""
        GOPROXY="https://proxy.golang.org,direct"
        GOROOT="/snap/go/6745"
        GOSUMDB="sum.golang.org"
        GOTMPDIR=""
        GOTOOLDIR="/snap/go/6745/pkg/tool/linux_amd64"
        GCCGO="gccgo"
        AR="ar"
        CC="gcc"
        CXX="g++"
        CGO_ENABLED="1"
        GOMOD="/home/voreny/projects/advent-of-code-solutions/2020/go.mod"
        CGO_CFLAGS="-g -O2"
        CGO_CPPFLAGS=""
        CGO_CXXFLAGS="-g -O2"
        CGO_FFLAGS="-g -O2"
        CGO_LDFLAGS="-g -O2"
        PKG_CONFIG="pkg-config"
        GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build708464149=/tmp/go-build -gno-record-gcc-switches"
      

Share the Go related settings you have added/edited

{
  "go.useLanguageServer": true,
  "go.alternateTools": {
    "go": "/snap/go/current/bin/go"
  }

Describe the bug

When debugging the program, a map whose keys are structs displays only a single entry, even though the length shows there are many.

image

Code sample:

package main

import "fmt"

type position struct {
	X, Y, Z, W int
}

func main() {
	p := map[position]bool{
		{1, 2, 3, 4}: true,
		{1, 2, 3, 5}: true,
		{1, 2, 3, 6}: true,
	}

	fmt.Println(p)
}

p will only show 1 entry

Even with String implemented for position, and changing the name to Position, the result is still the same

I would expect the debugger to list all entries in this case, possibly using String to serialize the map keys.

Steps to reproduce the behavior:

  1. Add a breakpoint on the line with fmt.Println in the snippet above
  2. Start the debugger
  3. Hover over the value of p. It will show only 1 entry, and length of 3

Screenshots or recordings

Added in the description

@Gelio Gelio changed the title Debugger lists only 1 entry in a map which keys are structs Debugger shows only 1 entry in a map which keys are structs Dec 17, 2020
@Gelio Gelio changed the title Debugger shows only 1 entry in a map which keys are structs Debugger shows only 1 entry in a map whose keys are structs Dec 17, 2020
@hyangah hyangah added the Debug Issues related to the debugging functionality of the extension. label Dec 17, 2020
@polinasok
Copy link
Contributor

polinasok commented Jan 7, 2021

While supporting compound values, the adapter erroneously treats all keys as scalars, using their variable "values" as-is. However, the value of a compound variable is not actually its unique value, but just a type placeholder with an option to expand for more info. And since all keys have the same type, they all end up with the exact same value, so the map ends up with only one entry in the UI.

From the log with "trace":"verbose"

VariablesResponse [
 {
  "name": "p",
  "value": "<map[main.position]bool> (length: 3)",
  "evaluateName": "p",
  "variablesReference": 1001 ### allows requests to expand for children
 }
]
### Children requested
VariablesResponse [ ### Contains all 3 entries
 {
  "name": "<main.position>",
  "value": "true",
  "evaluateName": "p[<main.position>]",
  "variablesReference": 0
 },
 {
  "name": "<main.position>",
  "value": "false",
  "evaluateName": "p[<main.position>]",
  "variablesReference": 0
 },
 {
  "name": "<main.position>",
  "value": "true",
  "evaluateName": "p[<main.position>]",
  "variablesReference": 0
 }
]

Related bug: #1085

@polinasok
Copy link
Contributor

polinasok commented Jan 7, 2021

This is how the new adapter in delve repo (go-delve/delve#1515) is handling this: go-delve/delve#2111 (comment)
I am open to alternative UI suggestions. Maybe instead of differentiating with a unique index, it would be better to use addresses instead.

Update 01/12: changed from index to address in keys in go-delve/delve#2291

@Gelio
Copy link
Author

Gelio commented Jan 7, 2021

@polinasok Thank you for taking a look at this issue.

Would it be possible to serialize the keys, e.g. by calling fmt.Sprint(key)?

btw. how can I use that new adapter in delve repo? Listing all keys and values with unique indices would be a usable workaround for me 🙂

@polinasok
Copy link
Contributor

polinasok commented Jan 13, 2021

The debugger backend doesn't operate on Go types. It has its own way to track and annotate types and variables that allows to power debugging. Therefore we would not be able to just serialize the actual key. There are also limitations on the size of the string value that we load once (delve default is 64). If we serialize a nested struct, we will end up trying to fit into a single line something that would require multiple lines with dlv cli and multiple expansions with vscode UI.

What you can do to serialize on your end is use call MyFunctionThatSerializes(mykey) from the Debug Console or from Watch.

The new adapter is experimental and work in progress. We are not actively advertising it yet as some key features are still missing, but we welcome any user testing if you want to check it out. As delve releases only once every several months, you need to get its latest revision on your own to try out the new adapter. You could launch ./dlv dap --listen=:54321 on the command line and then use debugServer":54321 from your launch.json to connect to this experimental version or you could try out debugAdapter2, but you would need to undo the disabling done in #960 (more details at #874). See more about overall integration plans at #23.

@hyangah
Copy link
Contributor

hyangah commented Jan 14, 2021

The new adapter is still accessible using the nightly version of this extension.

@polinasok
Copy link
Contributor

Summarizing earlier discussion. We will not be fixing this issue in the existing adapter. We have fixed this in the new adapter
image

However, displaying the key as just type+address is not as informative as one would like. @Gelio could you please file a separate issue for this feature request? Would something like what dlv cli does suit you?

(dlv) p mapWithLongCompoundKey
map[struct { main.i1 int; main.i2 int; main.i3 int; main.i4 int; main.i5 int; main.i6 int; main.i7 int; main.i8 int; main.i9 int; main.i10 int; main.i11 int; main.i12 int; main.i13 int; main.i14 int; main.i15 int; main.i16 int; main.i17 int; main.i18 int; main.i19 int; main.i20 int; main.i21 int; main.i22 int; main.i23 int; main.i24 int; main.i25 int; main.i26 int; main.i27 int; main.i28 int; main.i29 int; main.i30 int; main.i31 int; main.i32 int; main.i33 int; main.i34 int; main.i35 int; main.i36 int; main.i37 int; main.i38 int; main.i39 int; main.i40 int }]int [
        *{i1: 0, i2: 0, i3: 0, i4: 0, i5: 0, i6: 0, i7: 0, i8: 0, i9: 0, i10: 0, i11: 0, i12: 0, i13: 0, i14: 0, i15: 0, i16: 0, i17: 0, i18: 0, i19: 0, i20: 0, i21: 0, i22: 0, i23: 0, i24: 0, i25: 0, i26: 0, i27: 0, i28: 0, i29: 0, i30: 0, i31: 0, i32: 0, i33: 0, i34: 0, i35: 0, i36: 0, i37: 0, i38: 0, i39: 0, i40: 0}: 555, 
]

@Gelio
Copy link
Author

Gelio commented Mar 2, 2021

Closing this is understandable. Thanks for the summary.

I actually don't really know how we could proceed here and what would be a useful fix for the improvement here. Displaying all the entries in the map sounds great, so IMO it should be good enough 🙂 The dlv cli output also looks reasonable, since it seems to serialize the keys (or am I missing something?).

So, to sum up, do you want me to create a ticket essentially copying what you said in the comment above?

@polinasok
Copy link
Contributor

Closing this is understandable. Thanks for the summary.

I actually don't really know how we could proceed here and what would be a useful fix for the improvement here. Displaying all the entries in the map sounds great, so IMO it should be good enough 🙂 The dlv cli output also looks reasonable, since it seems to serialize the keys (or am I missing something?).

So, to sum up, do you want me to create a ticket essentially copying what you said in the comment above?

That would be great. We don't need the details about fixing the 1-entry issue in that but, just the info about displaying variables in a user-friendly way. If your point of view matches what I wrote, feel free to copy things. If you have any additional insights, please let us know. Thank you!

@Gelio
Copy link
Author

Gelio commented Mar 3, 2021

Thanks for the instructions 🙂 I've described the feature request in #1267

That forced me to explore the new adapter, which honestly, looks pretty dope 😄 Finally I'm able to see the contents of the struct keys 🎉 very cool

Also, that was my first time using dlv debug, which also was not too hard, and I enjoyed the experience 😄 Today I learned 🙂 thanks for delivering such tools!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Debug Issues related to the debugging functionality of the extension. FrozenDueToAge
Projects
None yet
Development

No branches or pull requests

4 participants