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 · 4 comments
Open

cmd/go2go: awkward composite literal edge case #45396

rogpeppe opened this issue Apr 5, 2021 · 4 comments
Assignees
Labels
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 griesemer added this to the Go1.18 milestone 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.

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
4 participants