-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
proposal: spec: relax structural matching for conversions #19778
Comments
cc: @griesemer |
This is something I've always found a little counterintuitive, especially if the underlying types are the same. I can think of a couple of times I've had to write my own It seems to make sense that if T1 and T2 are slices whose elements are all the same underlying types, they should be convertible without an allocation. |
@luna-duclos Note that for struct field tags, conversion is ignoring the tags "all the way down" - not just one level deep. That would be something to consider if we were to make this change. (Though this is not going to happen for Go 1.0 I suspect). |
This goes for non-struct types as wel. type MyType int You can't do this: a := []int{1, 2, 3}
b := []MyType(a) Instead, you have to do this: a := []int{1, 2, 3}
b := make([]MyType, len(a))
for i, v := range a {
b[i] = MyType(v)
} Making |
Seems related to #15209, which is about |
As I understand it, I think this proposal is asking for a concept that the language does not currently have: we permit converting That can't really be the rule, though, because it breaks for interface types. Consider
Can I write So the conversion rule must be something more complex than I wrote above. What is it? |
It can be done by adding a type convertion check along with underlying type equality. |
Change https://golang.org/cl/105937 mentions this issue: |
@vvoronin Thanks, but I'm not sure I understand your adjusted rule. Clearly it can't apply at top level, since at top level the types can not be converted. So, when does it apply? |
@ianlancetaylor I meant "when simple non-composite type can be type converted and have have identical memory layout, composite of that type also must be able to be type converted" For example: type A struct { A string }
type B struct { A string }
// we can convert this
var varA A = A(B{})
// and A and B have identical memory layout, so
var sliceOfB []B = []B([]A{}) type Y1 interface { M(X) }
type Y2 interface { M(int) }
var V1 Y1
var V2 Y2
// we cannot convert this
V2 = Y2(V1)
// so we cannot convert a slice or map of this // we can convert this
byteArray := []byte(`string`)
// but memory layout is different
// so we cannot convert a slice or map of this |
Currently, as of Go 1.8, one can convert between two identical types, A and B, defined as follows:
It is however not possible to convert between
[]A
and[]B
, even though the memory layout of both slices is identical, and one has to resort to following hackery to get both compile time checking and O(1) conversion time:This is often useful when different parts of an application are responsible for different parts of the handling of the lifetime of an object. For example, a database layer could return []A, which would be a type with
db:"foo"
decorators to help with database deserialization using the sqlx package, while thehttp handler wants to use []B, because it contains the field tags necessary for json serialization.
Currently, a copy or unsafe is required, I propose allowing slices with identical memory layouts to be converted between another, and to restrict this to only 1 level deep to reduce possible complexity in the compiler.
This is a similar reasoning why the spec was changed to allow structs with different field tags to be converted between eachother, and I believe it would help avoid usage of unsafe and copies in many applications which seperate out concerns between different layers.
The text was updated successfully, but these errors were encountered: