In order to avoid worrying about the distinction between value methods and pointer methods, in a generic function body all method calls will be pointer method calls. If necessary, the function body will insert temporary variables, not seen by the user, in order to get an addressable variable to use to call the method ...This makes it easier to understand which types satisfy a contract, and how a contract may be used. It has the drawback that in some cases a pointer method that modifies the value to which the receiver points may be called on a temporary variable that is discarded after the method completes. It may be possible to add a vet warning for a case where a generic function uses a temporary variable for a method call and the function is instantiated with a type that has only a pointer method, not a value method.
The motivation is to avoid requiring contracts to specify whether a method is a pointer method or a value method, just as we do not require interface types to specify whether a method is a pointer method or a value method.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcWgzkqS4GHH%2BbcQd6KNGJrRd1v2d0D2GU5LsomJF0SL%3Dw%40mail.gmail.com.
On Mon, Jul 29, 2019 at 2:25 PM, Ian Lance Taylor <ia...@golang.org> wrote:The motivation is to avoid requiring contracts to specify whether a method is a pointer method or a value method, just as we do not require interface types to specify whether a method is a pointer method or a value method.I'm not sure whether pointer method vs. value method is the distinction that needs to be made. For the general purpose of writing code that calls methods on arbitrary types, what we want to know is whether a type-parameterized function should assume it needs an addressable value or if it can use a non-addressable value of the parameter type to call a method. Any references/dereferences that need to be done can be done automatically as long as you know whether the value needs to be addressable and the code is written accordingly (i.e. without needing to take the address of an implicit variable). That might end up being represented in the language as though you're passing pointers into the methods, but I don't think that needs to map to whether the concrete method itself accepts a pointer or a value.To illustrate, if you havefunc Foo(type T ...)(slice []T) {for i := range slice {slice[i].DoStuff()}}what sort of bound do you need on `T` so that it can handle each combination of:1. `T` is passed a value type `Arg` or a pointer type `*Arg`, and2. `DoStuff` is defined on `Arg` or on `*Arg`?Why you sort of want is a constraint likeHasDoStuff(T), HasDoStuff(*T)where at least one or the other should capture the `DoStuff` method in each case, and thus the combined constraint should allow you to call methods on/involving addressable `T` values (potentially based on the fiction that the accepted type is `*T`). I'm not sure what the best way of write such a constraint is, though, or how common this kind of case is.
On Mon, Jul 29, 2019 at 2:25 PM, Ian Lance Taylor <ia...@golang.org> wrote:
On Mon, Jul 29, 2019 at 7:05 AM Ilia Choly <ilia...@gmail.com> wrote:
>
> When converting a non-pointer value to an interface, pointer methods cannot be used to satisfy the interface. Even though the compiler could add instructions to take the value's address, this is not allowed because it's error prone. Since pointer methods usually mutate the receiver, you don't want to be operating on a copy. https://play.golang.org/p/XDiki8_uHMs
>
> When reading the contracts proposal, I'm confused by the seemingly contradictory decision to allow pointer methods. https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md#methods
>
>> In order to avoid worrying about the distinction between value methods and pointer methods, in a generic function body all method calls will be pointer method calls. If necessary, the function body will insert temporary variables, not seen by the user, in order to get an addressable variable to use to call the method ...This makes it easier to understand which types satisfy a contract, and how a contract may be used. It has the drawback that in some cases a pointer method that modifies the value to which the receiver points may be called on a temporary variable that is discarded after the method completes. It may be possible to add a vet warning for a case where a generic function uses a temporary variable for a method call and the function is instantiated with a type that has only a pointer method, not a value method.
>
>
> The same example converted to use interfaces fails https://play.golang.org/p/FBbXQw7dKL6 What's the motivation for this design decision?
The motivation is to avoid requiring contracts to specify whether a
method is a pointer method or a value method, just as we do not
require interface types to specify whether a method is a pointer
method or a value method. It does make it possible to write certain
kinds of bugs, but it's not clear how much that arises in practice.
That said, it's likely that we will have to modify contracts to
require a pointer method in some cases, in order to separate defining
a variable of some type with invoking pointer methods on that
variable, so I would not be surprised if this aspect of the design
draft is changed.
Ian
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.
One way of avoiding this muddle between pointer and value methods would be to require that any type parameter (T say) which is subject to a contract cannot be replaced by a pointer type.
My suggestion was that you can't use a pointer type as a type parameter if the latter is subject to a contract.
In the case you mention, the contract could be expressed as a disjunction of value and pointer methods:
contract stringer(T) {
T String() string, *T String() string
}
On the other hand and more generally, not knowing whether the type parameter represented a pointer or a value might lead to some awkward coding. For example, you wouldn't be able to de-reference the type argument as it might not be a pointer.
It's clearly an area where some more thought is needed as Ian intimated earlier.
Alan
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/302c6d33-a8ea-4e8a-b02b-7cff1b3de1c5%40googlegroups.com.
On Tue, Jul 30, 2019 at 8:31 PM <alan...@gmail.com> wrote:My suggestion was that you can't use a pointer type as a type parameter if the latter is subject to a contract.I'm not sure I understand you. Wouldn't that preclude using a generic map with pointers as keys?
In the case you mention, the contract could be expressed as a disjunction of value and pointer methods:
contract stringer(T) {
T String() string, *T String() string
}Currently, Disjunctions only apply to a single type. You can't form expressions like this.IMO that's a good restriction to maintain. Because the more powerful the contract language becomes, the harder it'll be to make it useful.
On the other hand and more generally, not knowing whether the type parameter represented a pointer or a value might lead to some awkward coding. For example, you wouldn't be able to de-reference the type argument as it might not be a pointer.If a generic function wants to de-reference an argument, it should specify that as a pointer: func f(type T) (p *T)This is the same as with slices, maps, channels, functions or any composite type - you can't express "type parameter T should be a slice of some kind", because you are instead expected to just specify []T if you want a slice.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/cb9b37fc-19d4-4d25-bac8-72da1ade20a5%40googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/cb9b37fc-19d4-4d25-bac8-72da1ade20a5%40googlegroups.com.
Thus it would require 'T' to be a pointer - namely '*big.Int' - to match.It would mean that the receiver itself of the contract 'T Cmp(other T) int' is a pointer. Is it a case allowed by contracts?
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/cf04c27c-6ac0-4b64-96b4-f0e7a1a2a99d%40googlegroups.com.
The functionInit
cannot be instantiated with the typeMyInt
, as that type does not have a methodSet
; only*MyInt
hasSet
.
If a method is listed in a contract with a plainT
rather than*T
, then it may be either a pointer method or a value method ofT
.
&T
denoting addressable T
values, and let the compiler figure out matching up levels of indirection between generic code and the methods it calls, but this might add more complexity to the design than it's worth.--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/64567134-2fec-423c-8828-fed14f392fc7%40googlegroups.com.