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

Language specification: incorrect statement about method sets of pointer types #27786

Closed
pat42smith opened this issue Sep 20, 2018 · 6 comments
Closed

Comments

@pat42smith
Copy link

The language specification, under Method sets says

The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).

The text in parentheses seems to be incorrect if T itself is a pointer type. After

type X int
func (x X) foo() { ... }

the method sets of X and *X include foo, but that of **X does not.

(https://play.golang.org/p/8fvILyZeP1K)

@robpike
Copy link
Contributor

robpike commented Sep 21, 2018

The type X in your example (T in your prose) is not allowed to be a pointer type. That is, you cannot define methods on X if X is a pointer. As https://golang.org/ref/spec#Method_declarations says, the receiver type "must not be a pointer or interface type".

@robpike robpike closed this as completed Sep 21, 2018
@pat42smith
Copy link
Author

I must respectfully disagree. Eliding a bit of text, the "Method sets" section says

[for] any other type T ... The method set of the corresponding pointer type *T ... contains the method set of T

where "other" means "non-interface". In my example, X has a method foo defined on it, so foo is in the method set of X. Applying the above statement with T = X, then foo is in the method set of *X. Applying the statement again with T = *X, then foo is in the method set of **X, which is wrong.

Perhaps "any other type T" might be changed to "any other defined type T" or "any other named type T"?

In any case, this isn't terribly important to me. If you don't wish to change anything, I won't object.

@robpike
Copy link
Contributor

robpike commented Sep 21, 2018

The situation cannot arise. Try compiling the code at https://play.golang.org/p/4fWjEy73OTP 👍

package main

type T *int

func (t T) Foo() {}

There can never be a method on a **t for any type t.

If you can create a working example of the problem you are trying to show, please do so.

@pat42smith
Copy link
Author

pat42smith commented Sep 21, 2018

There can never be a method on a **t for any type t.

I understand this statement, and I agree it correctly describes the language.

My problem is that, in my reading of Method sets, it implies that there can be methods on a type **X. So it seems to me this section is not a correct description of the language.

By the nature of this problem, I can't produce an example that compiles. But please consider (https://play.golang.org/p/bsKB0B9jTDe).

package main

type X int
type T = *X

func (T) Foo() {}

func f(t T) { t.Foo() }		// ok

func g(t *T) { t.Foo() }	// error

This example contradicts the statement under Method sets that "the method set of ... *T ... contains the method set of T". True, in the example T is not a defined type, but I don't see anything in Method sets that requires T to be a defined type.

@robpike
Copy link
Contributor

robpike commented Sep 22, 2018

I think the spec is fine. You can't determine the full behavior of a feature from a sentence taken in isolation; it's part of a larger document. So I don't think anything's missing here, but I'll defer to @griesemer

@griesemer
Copy link
Contributor

The (almost) full text about method sets is

The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T). Further rules apply to structs containing embedded fields, as described in the section on struct types.

It starts with "all methods declared with receiver type T". It is not possible to have a receiver type T where T is a defined pointer type per the explanations about receivers in the method declaration section. Your most recent example uses a type alias (type T = *X) which is why the example works (at least for method f).

I agree with you that it's not completely trivial to cobble the various rules about method sets together (and it gets more complicate with embedded types in structs), and at some point it would be nice to clean this up a bit, but I also agree with @robpike that the spec is correct here.

Leaving this closed for now.

@golang golang locked and limited conversation to collaborators Sep 24, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants