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/go2go: awkward composite literal edge case #45396

Open
rogpeppe opened this issue Apr 5, 2021 · 6 comments
Open

cmd/go2go: awkward composite literal edge case #45396

rogpeppe opened this issue Apr 5, 2021 · 6 comments
Assignees
Milestone

Comments

@rogpeppe
Copy link
Contributor

@rogpeppe rogpeppe commented Apr 5, 2021

In this comment I brought up an edge case for type parameters:

type C interface {
	type map[int]string, []string, [2]string, struct{b1, b2 string}
}

const b1, b2 = 0, 1

func f[A C]() A {
	return A{
		b1: "a",
		b2: "b",
	}
}

Should this be valid or not?
Note that if C contains only one of any of the type list above, the code works for that type.

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Apr 5, 2021

@griesemer
Copy link
Contributor

@griesemer griesemer commented Apr 5, 2021

My inclination would be that this shouldn't be valid. More generally, we need to pin down exactly what the currently proposed rules mean when they say "all operations supported by all types in a type set" will be permitted.

@apparentlymart
Copy link

@apparentlymart apparentlymart commented Apr 9, 2021

FWIW as just a user without any particular investment in any specific answer to this question, my first intuition told me that this would not be valid because I see four different semantic "operations" here, even though all of them have the same syntax:

  • Construct a map value
  • Construct a slice value (and its underlying array)
  • Construct an array value
  • Construct a value of this particular struct type

However, this did get me thinking about other similar situations where the syntax could be said to overlap even though the semantics might not:

type C interface {
	type map[int]string, []string, chan string. []int, chan int
}

func f[A C]() A {
	return make(A)
}

make is defined in the specification as a "built in function", which suggests to me that there is only one "thing" represented by that keyword make, and that thing happens to take a type as a first argument. In which case it would stand to reason that it could accept any type parameter A which is provably a slice, map, or channel type.

Which then led me back to ambivalence, because I'm not sure it feels justified to me for make to have different rules than a composite literal just because one of them happens to be a predeclared function while the other has a specialized grammar associated with it; they both have comparable purposes in the language, and both are defined as a singular "thing" in the spec which happens to take a type as an argument.

Having written this out I find myself doubting whether I've actually added anything to the discussion, because I left feeling far less convinced than I started! But I hope at least the analogy to make is a useful example to consider while thinking about this.

@griesemer
Copy link
Contributor

@griesemer griesemer commented Apr 9, 2021

@apparentlymart I think at the end of the day this is the kind of thing we need to explicitly write down in the spec. make(A) is an "operation" applied to an operand, similar to x + 1 where + is an operation applied to x where x might be of a type parameter type. But the struct composite literal

A{
	b1: "a",
	b2: "b",
}

where b1 and b2 are actual struct field names is something different (and different from the ones where the b1 and b2 are key values). We probably don't want to allow this.

@kfsone
Copy link

@kfsone kfsone commented Apr 21, 2021

I want everyone to LOOK, A SQUIRREL before someone else comes in to suggest lua-style [b1] syntax or something equally heinous.

I do think this is something that will need a solution but I think that the introduction of generics can survive the inability to memberwise-construct compounds: so I propose completely disallowing it in the initial launch of generics.

func f[A C]() A {
  a := A{ x: 1 }

might produce the diagnostic

error: generic functions may not construct a compound literal with named fields. see ...link...

Better to have this omission than to reinvent c++ templates.

@griesemer
Copy link
Contributor

@griesemer griesemer commented Sep 24, 2021

This will not be in the Go1.18 release. Leaving open for future discussion.

@griesemer griesemer removed this from the Go1.18 milestone Sep 24, 2021
@griesemer griesemer added this to the Go1.19 milestone Sep 24, 2021
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
5 participants