proposal: Go 2: a new read-only type proposal #29392
Labels
FrozenDueToAge
LanguageChange
Suggested changes to the Go language
Proposal
v2
An incompatible library change
Milestone
There has already been many read-only types related proposals.
But I feel they are too complicated to destroy the simplicity of Go.
So here I try to make a simpler one.
I propose to add a type literal modifier,
@
, which meansassignment sign =
(The literal choice is not the core of this proposal, it can be designed in a different style.).A read-only type with a foundation type
T
can be represented as@T
, which means values of@T
can only be used as source values and can't be used as destination values.A value of a read-only type must be bound to (a copy of) of another value.
If it is a variable, the binding happens when it is declared.
This means a read-only value is addressable and can be taken address.
But (the direct part of) a read-only value can never be modified (after the value is declaration).
[update 4]:
A value of type
@T
can always be assigned to a value of typeT
, the reason is in the assignment process, a value of type@T
is copied to theT
value.A value of type
T
can be assigned to a value of type@T
, but only when the@T
value is declared.In other words, values of(conversion != assignment)@T
can be implicitly converted to typeT
, and vice versa.What prevents a value of a source type from being assigned to a value of a destination type is whether or not the source type has a more restricted base/element type than the destination type.
The read-only in this proposal means that, for example, if the base type of a pointer value is read-only, then compilers will forbid modifying the value referenced by the pointer
through the pointer
, but the value referenced by the pointer can be modified through other pointers referencing the value, or the value can even be modified directly. Surely, if the type of a value is read-only, then there are no ways to modify the value. It is just that mutable values sometimes can be viewed as read-only values, but read-only values will never be viewed as mutable values.One example:
Another example:
In fact,
@struct {pages int; title string}
and@struct {pages @int; title @string}
are equivalent. The same,@[N]T
and@[N]@T
are equivalent.struct {pages @int; title string}
is not a valid type literal.[N]@T
is not a valid type literal.Strings can be viewed as read-only
byte
containers.Slices:
The meaning of the
@
modifier is a little different for map types.map[@K]T
means no new keys are allowed to be appended into the map value.map[@K]@T
means no new enries are allowed to be appended into the map value.map[K]@T
is equivalent to typemap[@K]@T
For channel types:
([update 2]: For reflection purpose,chan @int
andchan int
are equivalent.chan <-@int
andchan <-int
are equivalent.<-chan @int
and<-chan int
are equivalent. This means when a value is received from achan <-@int
channel, the type of the value can be viewed as either@int
orint
. But for the deterministic in reflection functions and compatibility, its type should be viewed asint
.chan @int
andchan int
should not be viewed as equivalent types.)The method set of
T
is a super set of@T
. The method set of*@T
is a super set of@T
. The method set of*T
is a super set of*@T
.In implementations, the proposal needs an extra bit stored in a pointer value to indicate the value referenced by the pointer is immutable. For 64-bit archs, this is not a big problem, but it may be a drawback for 32-bit archs. Besides this drawback, this proposal may cause a small overhead for pointer operations.(no these drawbacks after thinking for awhile, for the read-only info is stored with types instead of values.)[update 1]
For most scenarios, whether or not the dynamic type of an interface value is read only is not important. But for reflection purpose, making the difference is needed. So the read-only info will be kept in the dynamic type info stored in an interface value.
[update 2]: see above channel section.
[update 3]
For functions,
it is a nonsense to make function results read only. In other words, though syntax doesn't forbid read-only results, but in practice, read-only results are almost totally useless, for their final values will be always zero values. Function results should be always not read only.It is a nonsense to make function parameters and results read only. The reason is arguments and returns of function called are always copied. But if a parameter or a result is of a container (or pointer) type, the read-only info for its element type (or base type) is important.For clarity purpose, using read-only parameters and results should be forbidden.
(In fact, read-only parameters and results of a function are not totally non-sense, they are just non-sense for callers of the function. They are still meaningful in the function internal. In other words, in the API docs of a function, none of the parameters and results should present as read-only. Function type
func (@T1) @T2
should be equivalent to function typefunc (T1) T2
.)BTW, in fact, a function declaration can be viewed as a read-only function variable declaration:
is equuvalent to
[update 4]: see one of the beginning paragraphs.
The text was updated successfully, but these errors were encountered: