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: define "interface value" #8150

Open
gopherbot opened this issue Jun 4, 2014 · 11 comments
Open

spec: define "interface value" #8150

gopherbot opened this issue Jun 4, 2014 · 11 comments
Assignees
Milestone

Comments

@gopherbot
Copy link

by gnormington@gopivotal.com:

The spec mentions "interface value" seven times but does not define the term.
Defining the term carefully would help to avoid some common misunderstandings, most
notably http://golang.org/doc/faq#nil_error.

The spec says "Two interface values are equal if they have identical dynamic types
and equal dynamic values or if both have value nil." from which we can infer:

1. An interface value may have a dynamic type, and

2. An interface value may have a dynamic value, and either

3a. An interface value may have value nil, or

3b. An interface value may be nil.

I think the spec sentence should really say "Two interface values are equal if
[...] or if both are nil." which would imply 3b rather than 3a.

The spec also says "The static type (or just type) of a variable is the type
defined by its declaration. Variables of interface type also have a distinct dynamic
type, which is the actual type of the value stored in the variable at run time. The
dynamic type may vary during execution but is always assignable to the static type of
the interface variable. For non-interface types, the dynamic type is always the static
type." from which we can additionally infer (assuming a variable of interface type
always contains an interface value):

4. An interface value has a static type which is the interface type of the value.

Notice that 4 doesn't appear to be true for nil interface values, so I think the above
paragraph needs fixing too ("[...] Non-nil variables of interface type also have a
distinct dynamic type, [...]")

Although I suspect the FAQ isn't normative, it provides a helpful insight, "[...]
the return value is an error interface value holding (*MyError, nil)", from which
we can infer:

5. The interface value may have a nil dynamic value.

Here is a speculative description of an interface value, with some educated guesses
thrown in, to give an impression of where all this might lead:

An interface value is the value of a variable of interface type. An interface value is
either nil or has both a dynamic type and a dynamic value.

A nil interface value always results from [is assigned from, passed as a parameter,
returned, etc.] a literal nil value since any other value has a non-nil dynamic type.

The static type of an interface value is an interface type [and it would be nice to
spell out *which* interface type!].

If a non-nil interface value has a non-nil dynamic value, then the actual type of the
dynamic value is equal to the dynamic type of the interface value. The dynamic value of
a non-nil interface value may be nil.

The dynamic type of a non-nil interface value is never nil. The dynamic type of a
non-nil interface value implements the static type of the interface value.

An interface value compares (==) equal to nil if and only if it is nil; a non-nil
interface value never compares (==) equal to nil. [This latter statement may be out of
place in the definition of interface value, but should at least be linked to from the
definition. But given http://golang.org/doc/faq#nil_error, it may be worth having some
repetition of this point.]
@ianlancetaylor
Copy link
Contributor

Comment 1:

Labels changed: added repo-main, release-go1.4.

@cznic
Copy link
Contributor

cznic commented Jun 4, 2014

Comment 2:

An interface value is an instance of an interface type[0] as is an integer value an
instance of an integer type.
An interface has always both a static type and a dynamic type.
An interface value (IV) can be nil and can hold a nil value. The former situation
applies when the IV has no dynamic type because nothing has been assigned to the IV. The
later situation applies when the dynamic type of the IV is nil.
The static type of an IV is the type IV was declared to be:
        var v1 interface{}
        var v2 myInterface
        var v3 int
The static type doesn't change exactly as the type of v3 never changes.
Etc., ie. all (of the other) observations in the OP are already well defined in the
language specification.
  [0]: http://golang.org/ref/spec#Interface_types

@griesemer
Copy link
Contributor

Comment 3:

The term interface value is misleading as it implies that there's a value of type
interface, but in fact there are no values of such types because interfaces types are
abstract types, with no concrete instances.

Owner changed to @griesemer.

Status changed to Accepted.

@gopherbot
Copy link
Author

Comment 4 by gnormington@gopivotal.com:

Thanks for the fast feedback.
> An interface value is an instance of an interface type[0]
> as is an integer value an instance of an integer type.
Of course, but that just pushes the problem back to what it means to instantiate an
interface type, which I don't think is clear in the spec.
> An interface has always both a static type and a dynamic type.
I find this really confusing. The spec defines "interface" as follows: "An interface
type specifies a method set called its interface."
How can a method set have a dynamic type? Surely only values have dynamic types?
> An interface value (IV) can be nil and can hold a nil value.
Perhaps "can hold a nil dynamic value" would be less confusing, if that's what you mean.
> The former situation applies when the IV has no dynamic
> type because nothing has been assigned to the IV. The later
> situation applies when the dynamic type of the IV is nil.
You seem to be saying that:
var v1 myInterface
results in v1 being nil and having no dynamic type whereas
var v1 myInterface
v1 = nil
results in v1 holding a nil value and having a nil dynamic type. Agreed?
But there is another case to consider: an IV which has a non-nil dynamic type and a nil
dynamic value, e.g. (*MyError, nil) from the FAQ.
> The static type of an IV is the type IV was declared to be:
>
>        var v1 interface{}
>        var v2 myInterface
>        var v3 int
>
> The static type doesn't change exactly as the type of v3 never changes.
Sure.
>
> Etc., ie. all (of the other) observations in the OP are already
> well defined in the language specification.
If by OP, you mean the opening text of this bug report, I'm afraid I disagree. With a
bit of polishing up (or even correction - see above), the following statements would be
a valuable addition to the spec:
> An interface value (IV) can be nil and can hold a nil value.
> The former situation applies when the IV has no dynamic
> type because nothing has been assigned to the IV. The later
> situation applies when the dynamic type of the IV is nil.
but, if these are already well defined in the spec, I'm wondering where as I've clearly
not found the right section yet.

@gopherbot
Copy link
Author

Comment 5 by gnormington@gopivotal.com:

> The term interface value is misleading as it implies
> that there's a value of type interface, but in fact
> there are no values of such types because interfaces
> types are abstract types, with no concrete instances.
This I understand. Thank you!
However, that seems to leave the FAQ high and dry. Doesn't the spec needs to say
something from which the FAQ could be inferred?

@griesemer
Copy link
Contributor

Comment 6:

A variable of (static) interface type can hold a value of concrete (non-interface) type;
that type is also called the "dynamic type" of that variable (since it can change
dynamically during the run of a program). Each such value's concrete type (== the
variable's dynamic type) "implements" the interface type of the variable. The variable
value may also be nil, and in this case has no dynamic type because there's no concrete
value in the variable (and I'm casually claiming that "nil" is not a concrete value). A
value can never have interface type.
But let's not discuss this in this CL. There are already several issues open that ask
for the clarification of interface types, so eventually we will get to them. The CLs are
the place for the refinement.
This is also not urgent since all implementations agree on what is meant (even if it's
not written down clearly); and generally programmers seem to understand the intent.

@gopherbot
Copy link
Author

Comment 7 by gnormington@gopivotal.com:

Ok, I'll look forward to a more precise description of interface types and variables of
interface types. I'm happy to review any proposal and provide early feedback - just post
a link here if I can be of service.
Although I agree that programmers seem to be getting by with the current level of
explanation of interface types, I don't feel there has yet been a sufficiently
compelling and precise explanation and, when there is, I think all Go programmers will
be considerably better off.

@gopherbot
Copy link
Author

Comment 8:

CL https://golang.org/cl/149360043 mentions this issue.

@griesemer
Copy link
Contributor

Comment 9:

Labels changed: added documentation.

@rsc
Copy link
Contributor

rsc commented Oct 28, 2014

Comment 10:

Labels changed: added release-go1.4maybe, removed release-go1.4.

@rsc
Copy link
Contributor

rsc commented Nov 6, 2014

Comment 11:

Labels changed: added release-go1.5, removed release-go1.4maybe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants