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

spec: some wording need to be adjusted for embedding alias of pointer types #22005

Open
go101 opened this issue Sep 24, 2017 · 19 comments
Open

spec: some wording need to be adjusted for embedding alias of pointer types #22005

go101 opened this issue Sep 24, 2017 · 19 comments
Assignees
Milestone

Comments

@go101
Copy link

@go101 go101 commented Sep 24, 2017

Now, the wording is

An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type.

However aliases of *T can also be embedded.

@go101
Copy link
Author

@go101 go101 commented Sep 24, 2017

btw, some wording for the receiver type requirements in the Method declarations may also need to be adjusted, as aliases of *T can also be used as receiver types.

@griesemer griesemer self-assigned this Sep 24, 2017
@griesemer
Copy link
Contributor

@griesemer griesemer commented Sep 24, 2017

I think those are still correct. We still have named types (any type that has a name); it's just that it may be a defined or an alias type.

The rules for embedding allow alias types.

The rules for method receivers explicitly say that the receiver type must be defined in the same package.

Is there anything specific that you believe needs to be fixed (and why)?

@go101
Copy link
Author

@go101 go101 commented Sep 25, 2017

Maybe my English understanding is not correct, for embeddable types, spec says

..., and T itself may not be a pointer type.

However, T can be a pointer type (as an alias)

type T = *int
type S struct{
	T // T is a pointer
}

And for method receivers, the receiver type must be defined in the same package..
However, aliases (which are not defined) declared in the same package can also be used as receiver types.

type S struct{}
type T = S
type P = *S
func (T) f() {}
func (*T) g() {}
func (P) h() {}

Maybe, mention that declared methods on an alias of a type has the same effect as declaring methods on the type itself would be better.

@griesemer
Copy link
Contributor

@griesemer griesemer commented Sep 25, 2017

Hm, you have a point. I'll look into this. Thank you!

@griesemer griesemer added this to the Go1.10 milestone Sep 25, 2017
@myitcv
Copy link
Member

@myitcv myitcv commented Sep 26, 2017

However, aliases (which are not defined) declared in the same package can also be used as receiver types.

...

Maybe, mention that declared methods on an alias of a type has the same effect as declaring methods on the type itself would be better.

I think this is implicit in the definition of an alias itself; i.e. that an alias is just that, an alias for a defined type (recursive definition), not a type in and of itself.

So in your method examples the receiver types are:

type S struct{}
type T = S
type P = *S
func (T) f() {}   // S
func (*T) g() {}  // *S
func (P) h() {}   // *S

it's just that we're using aliases to refer to those two types.

Similarly with embedding:

type T1 = *int
type S struct{
	T1 // *int; T = int in spec terms (i.e. the "may not be a pointer type" bit)
}
@golang golang deleted a comment from daiweisong Sep 26, 2017
@go101
Copy link
Author

@go101 go101 commented Sep 26, 2017

@myitcv yes, no problems on the mechanism here. It is just that some terminologies and some wording need to be clarified. For example, what is a named type? Can an alias be called a type? Is alias of a defined type can also be called defined type? etc.

@rsc rsc modified the milestones: Go1.10, Go1.11 Dec 14, 2017
@go101
Copy link
Author

@go101 go101 commented May 10, 2018

I feel some wording for the method documentations of the refect.Type type also need adjusted.

For example, the word "unnamed" may be better to change to "non-defined".

@gopherbot
Copy link

@gopherbot gopherbot commented May 10, 2018

Change https://golang.org/cl/112717 mentions this issue: reflect: use 'defined' rather than 'named', use 'embedded' rather than 'anonymous'

gopherbot pushed a commit that referenced this issue May 10, 2018
…n 'anonymous'

On the API level this is just an update of the documentation to match
the current spec more closely.

On the implementation side, this is a rename of various unexported names.

For #22005.

Change-Id: Ie5ae32f3b10f003805240efcceab3d0fd373cd51
Reviewed-on: https://go-review.googlesource.com/112717
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
@ianlancetaylor ianlancetaylor modified the milestones: Go1.11, Unplanned Jun 29, 2018
@go101
Copy link
Author

@go101 go101 commented Apr 9, 2019

Are the following descriptions accurate?

  • A type name T can be embedded as an embedded field unless T denotes a pointer type which base type is either a pointer or an interface type.
  • A pointer type *T, where T is a type name denoting the base type of the pointer type, can be embedded as an embedded field only if T doesn't denote a pointer or interface type.
@griesemer
Copy link
Contributor

@griesemer griesemer commented Apr 10, 2019

@go101 I believe those descriptions are still accurate; by type name we do mean a name denoting a type (and it could be an alias).

@go101
Copy link
Author

@go101 go101 commented Apr 10, 2019

An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type.

The above shown current description excludes the following T alias.

type T = *int
type S struct{
	T // T is a pointer
}
@go101
Copy link
Author

@go101 go101 commented Apr 11, 2019

Or the following one?

An embedded field must be specified as the form T or *T, where T is a type name and the embedded type may not be a pointer type whose base type is a pointer or interface type.

@go101
Copy link
Author

@go101 go101 commented Apr 11, 2019

A question, why pointer types whose base types are pointer and interface types can't be embedded?
If they can, the rule can be much simplified as An embedded field must be specified as a type name or a type literal which can provide an identifier as the field name.

@griesemer
Copy link
Contributor

@griesemer griesemer commented Apr 11, 2019

@go101 Originally, we wanted to avoid situations such as **T embeddings, etc. There are also interactions with lookup of embedded fields and methods. You're right that there are certainly unanswered questions here, and possibly inconsistencies. I'd love to simplify this, as it is only going to get more complex if we have generics as well. Thanks for pointing out the inconsistencies. We will get to this eventually; but at the moment it is not a high priority.

@griesemer griesemer modified the milestones: Unplanned, Go1.14 Apr 11, 2019
@go101
Copy link
Author

@go101 go101 commented Apr 19, 2019

I think I got why pointer types whose base types are pointer and interface types can't be embedded.
The reason is, except pointer and interface types, for each type T of other types, the method set of *T is always a super-set of T.

@go101
Copy link
Author

@go101 go101 commented Nov 3, 2019

Just found my above description is not accurate. It missed the following highlighted case:

  • A type name T can be embedded as an embedded field unless T denotes a defined pointer type or a pointer type which base type is either a pointer or an interface type.
  • A pointer type *T, where T is a type name denoting the base type of the pointer type, can be embedded as an embedded field unless type name T denotes a pointer or interface type.
@go101
Copy link
Author

@go101 go101 commented Dec 14, 2019

I just noticed that, gc and gccgo have different behaviors on this inaccuracy.
For the following code, gc compiles it okay, but gccgo reports an error.

package main

type P = *bool
type T struct {
	P
}

func main() {}
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Dec 14, 2019

@go101 At first glance I think that is a gccgo bug. Want to file an issue for that? Thanks.

@griesemer
Copy link
Contributor

@griesemer griesemer commented Dec 16, 2019

Just FYI: go/types also accepts this code.

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
6 participants
You can’t perform that action at this time.