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

cmd/compile: confusing error: cannot use x (variable of type []string) as []string value #58611

Closed
ldemailly opened this issue Feb 20, 2023 · 10 comments
Assignees
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@ldemailly
Copy link

ldemailly commented Feb 20, 2023

What version of Go are you using (go version)?

Same for go 1.18 to 1.20.1

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

n/a

What did you do?

type Set[T comparable] map[T]struct{}

func (s *Set[string]) String() string {
	keys := make([]string, 0, len(*s))
	for k := range *s {
		keys = append(keys, k)
	}
	sort.Strings(keys)             // cannot use keys (variable of type []string) as []string value in argument to sort.Strings (!!!)
	return strings.Join(keys, ",") // cannot use keys (variable of type []string) as []string value in argument to strings.Join (!!!)
}

https://go.dev/play/p/YhkT3b691OB

What did you expect to see?

cannot use keys (variable of type []comparable) as []string value in argument to sort.Strings 

instead

What did you see instead?

cannot use keys (variable of type []string) as []string value in argument to sort.Strings

ps: I'm now aware that using Set[string] in that context doesn't specialize the Set to string, but this was super confusing
An even better error message could be in the receiver to say something
Set[string] should be Set[T comparable] or some such as while string isn't a reserved keyword (sadly in this case) it's very confusing

@ldemailly ldemailly changed the title go compiler bug/confusing error go compiler bug/confusing error: cannot use x (variable of type []string) as []string value Feb 20, 2023
@zigo101
Copy link

zigo101 commented Feb 21, 2023

The string in the method is a type parameter. The whole method declaration body is equivalent to

func (s *Set[T]) String() T {
	keys := make([]T, 0, len(*s))
	for k := range *s {
		keys = append(keys, k)
	}
	sort.Strings(keys)             // cannot use keys (variable of type []T) as []string value in argument to sort.Strings (!!!)
	return strings.Join(keys, ",") // cannot use keys (variable of type []T) as []string value in argument to strings.Join (!!!)
}

@ldemailly
Copy link
Author

Yes I realized as much after scratching my head and asking for help, but that doesn't make the compiler message helpful as it is

@ianlancetaylor
Copy link
Contributor

Please see https://go.dev/doc/faq#types_in_method_declaration .

But, yes, perhaps the compiler can give a better error message if the error has two different types with the same name.

@ianlancetaylor ianlancetaylor changed the title go compiler bug/confusing error: cannot use x (variable of type []string) as []string value cmd/compile: confusing error: cannot use x (variable of type []string) as []string value Feb 21, 2023
@ianlancetaylor
Copy link
Contributor

CC @griesemer

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Feb 21, 2023
@ianlancetaylor ianlancetaylor added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Feb 21, 2023
@ianlancetaylor ianlancetaylor added this to the Backlog milestone Feb 21, 2023
@ldemailly
Copy link
Author

ldemailly commented Feb 21, 2023

Thanks!

Someone suggested to use [type] instead of type for that error / generic type names, that would have given me a better hint (though []comparable would have been even better)

@griesemer
Copy link
Contributor

Agreed that the compiler should do a better job in cases like these.

@griesemer griesemer self-assigned this Feb 21, 2023
@griesemer griesemer modified the milestones: Backlog, Go1.21 Feb 21, 2023
@Merovius
Copy link
Contributor

@ldemailly FWIW I don't think that using [T] instead of T for type parameters would be a good fix, as you get the same problem if you do type string int. Though arguably that would be less confusing, as it is less obvious that the type parameter name introduces a new type, while type string int is pretty abundantly clear. Either way, I also don't think it's obvious that [T] refers to a type parameter and [][string] most definitely looks confusing.

IMO it would be a better fix if the compiler would say something like can't use []string (with string definde in foo.go:42:23) as []string (with string predeclared) or something, if the stringified type names are equal. No idea how complex that'll be. I'm sure someone can figure something out that's clear.

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/470075 mentions this issue: go/types, types2: point out type parameters with predeclared names in errors

@ldemailly
Copy link
Author

Thx for super quick fix! one question though, I am not super clear from the mr what the new error message looks like?

@griesemer
Copy link
Contributor

For the program in the playground it will now report:

./x.go:15:15: cannot use keys (variable of type []string /* with string declared at ./x.go:10:14 */) as []string value in argument to sort.Strings
./x.go:16:9: cannot use strings.Join(keys, ",") (value of type string) as string /* with string declared at ./x.go:10:14 */ value in return statement
./x.go:16:22: cannot use keys (variable of type []string /* with string declared at ./x.go:10:14 */) as []string value in argument to strings.Join

It's not the most beautiful error message but it hopefully makes it clear which of the string types is user-defined. This is a rare case, after all, and pointing out that something unusual is happening should help a lot.

More generally, whenever a type parameter name matches a name of a predeclared type or object (even true or false) we get the special annotation. Again, usually programs won't use names of predeclared objects in situations like these.

(The new error message should actually be present in the dev playground, but it doesn't appear to be up-to-date at the moment.)

johanbrandhorst pushed a commit to Pryz/go that referenced this issue Feb 22, 2023
… errors

If a type parameter has the same name as a predeclared type, error
messages can be very confusing. In these rare cases, explicitly
point out where the type parameter is declared (types2) or that it
is a type parameter (go/types).

(We can't point out where the type parameter is declared in go/types
because we don't have access to the file set in the type writer at
the moment.)

Fixes golang#58611.

Change-Id: I5c150c2b0afae5fad320821e7e5935090dc2ef4c
Reviewed-on: https://go-review.googlesource.com/c/go/+/470075
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
@golang golang locked and limited conversation to collaborators Feb 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

6 participants