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 · 15 comments

Comments

Projects
None yet
6 participants
@go101
Copy link

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Member

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 Sep 26, 2017

@go101

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link

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

reflect: use 'defined' rather than 'named', use 'embedded' rather tha…
…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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.