mirror of
https://github.com/golang/go
synced 2024-09-05 16:04:50 +00:00
spec: generalize method sets and interface types to type sets
This is the first of several CLs that update the existing Go 1.17 spec for type parameters. This CL updates the section on method sets and interface types. It also adds "any", "comparable" to the list of predeclared identifiers. Change-Id: I0ce25dc02791c33150c0d949528512610faf3eab Reviewed-on: https://go-review.googlesource.com/c/go/+/362999 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
d8f7a64519
commit
f6647f2e3b
245
doc/go_spec.html
245
doc/go_spec.html
|
@ -1,9 +1,18 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of Oct 15, 2021",
|
||||
"Subtitle": "Version of Nov 17, 2021",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
<h2>Draft Go 1.18 Specification - Work in Progress </h2>
|
||||
|
||||
<p>
|
||||
<strong>
|
||||
For the pre-Go1.18 spec see
|
||||
<a href="/doc/go1.17_spec.html">The Go Programming Language Specification</a>.
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
|
||||
<p>
|
||||
|
@ -266,7 +275,7 @@ The following character sequences represent <a href="#Operators">operators</a>
|
|||
* ^ *= ^= <- > >= { }
|
||||
/ << /= <<= ++ = := , ;
|
||||
% >> %= >>= -- ! ... . :
|
||||
&^ &^=
|
||||
&^ &^= ~
|
||||
</pre>
|
||||
|
||||
<h3 id="Integer_literals">Integer literals</h3>
|
||||
|
@ -829,27 +838,41 @@ The underlying type of <code>[]B1</code>, <code>B3</code>, and <code>B4</code> i
|
|||
</p>
|
||||
|
||||
<h3 id="Method_sets">Method sets</h3>
|
||||
|
||||
<p>
|
||||
A type has a (possibly empty) <i>method set</i> associated with it.
|
||||
The method set of an <a href="#Interface_types">interface type</a> is its interface.
|
||||
The method set of any other type <code>T</code> consists of all
|
||||
The <i>method set</i> of a type determines the methods that can be
|
||||
<a href="#Calls">called</a> on an <a href="#Operands">operand</a> of that type.
|
||||
Every type has a (possibly empty) method set associated with it:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>The method set of a <a href="#Type_definitions">defined type</a> <code>T</code> consists of all
|
||||
<a href="#Method_declarations">methods</a> declared with receiver type <code>T</code>.
|
||||
The method set of the corresponding <a href="#Pointer_types">pointer type</a> <code>*T</code>
|
||||
is the set of all methods declared with receiver <code>*T</code> or <code>T</code>
|
||||
(that is, it also contains the method set of <code>T</code>).
|
||||
Further rules apply to structs containing embedded fields, as described
|
||||
in the section on <a href="#Struct_types">struct types</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The method set of a <a href="#Pointer_types">pointer</a> <code>*T</code>
|
||||
to a defined type <code>*T</code>
|
||||
(where <code>T</code> is neither a pointer nor an interface)
|
||||
is the set of all methods declared with receiver <code>*T</code> or <code>T</code>.
|
||||
</li>
|
||||
|
||||
<li>The method set of an <a href="#Interface_types">interface type</a> is the intersection
|
||||
of the method sets of each type in the interface's <a href="#Interface_types">type set</a>
|
||||
(the resulting method set is usually just the set of declared methods in the interface).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Further rules apply to structs (and pointer to structs) containing embedded fields,
|
||||
as described in the section on <a href="#Struct_types">struct types</a>.
|
||||
Any other type has an empty method set.
|
||||
In a method set, each method must have a
|
||||
<a href="#Uniqueness_of_identifiers">unique</a>
|
||||
non-<a href="#Blank_identifier">blank</a> <a href="#MethodName">method name</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The method set of a type determines the interfaces that the
|
||||
type <a href="#Interface_types">implements</a>
|
||||
and the methods that can be <a href="#Calls">called</a>
|
||||
using a receiver of that type.
|
||||
In a method set, each method must have a
|
||||
<a href="#Uniqueness_of_identifiers">unique</a>
|
||||
non-<a href="#Blank_identifier">blank</a> <a href="#MethodName">method name</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="Boolean_types">Boolean types</h3>
|
||||
|
@ -1236,23 +1259,33 @@ func(n int) func(p *T)
|
|||
<h3 id="Interface_types">Interface types</h3>
|
||||
|
||||
<p>
|
||||
An interface type specifies a <a href="#Method_sets">method set</a> called its <i>interface</i>.
|
||||
A variable of interface type can store a value of any type with a method set
|
||||
that is any superset of the interface. Such a type is said to
|
||||
<i>implement the interface</i>.
|
||||
An interface type defines a <i>type set</i>.
|
||||
A variable of interface type can store a value of any type that is in the type
|
||||
set of the interface. Such a type is said to <i>implement the interface</i>.
|
||||
The value of an uninitialized variable of interface type is <code>nil</code>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
InterfaceType = "interface" "{" { ( MethodSpec | InterfaceTypeName ) ";" } "}" .
|
||||
MethodSpec = MethodName Signature .
|
||||
MethodName = identifier .
|
||||
InterfaceTypeName = TypeName .
|
||||
InterfaceType = "interface" "{" { InterfaceElem ";" } "}" .
|
||||
InterfaceElem = MethodElem | TypeElem .
|
||||
MethodElem = MethodName Signature .
|
||||
MethodName = identifier .
|
||||
TypeElem = TypeTerm { "|" TypeTerm } .
|
||||
TypeTerm = [ "~" ] Type .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
An interface type may specify methods <i>explicitly</i> through method specifications,
|
||||
or it may <i>embed</i> methods of other interfaces through interface type names.
|
||||
An interface type is specified by a list of <i>interface elements</i>.
|
||||
An interface element is either a method or a type element,
|
||||
where a type element is a union of one or more type terms.
|
||||
A type term is either a single type or a single underlying type.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In its most basic form an interface specifies a (possibly empty) list of methods.
|
||||
The type set defined by such an interface is the set of types which implement all of
|
||||
those methods, and the corresponding <a href="#Method_sets">method set</a> consists
|
||||
exactly of the methods specified by the interface.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -1297,15 +1330,19 @@ then the <code>File</code> interface is implemented by both <code>S1</code> and
|
|||
</p>
|
||||
|
||||
<p>
|
||||
A type implements any interface comprising any subset of its methods
|
||||
and may therefore implement several distinct interfaces. For
|
||||
instance, all types implement the <i>empty interface</i>:
|
||||
Every type that is a member of the type set of an interface implements that interface.
|
||||
Any given type may implement several distinct interfaces.
|
||||
For instance, all types implement the <i>empty interface</i> which stands for the set of all types:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
interface{}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
For convenience, the predeclared type <code>any</code> is an alias for the empty interface.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Similarly, consider this interface specification,
|
||||
which appears within a <a href="#Type_declarations">type declaration</a>
|
||||
|
@ -1334,12 +1371,16 @@ as the <code>File</code> interface.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
An interface <code>T</code> may use a (possibly qualified) interface type
|
||||
name <code>E</code> in place of a method specification. This is called
|
||||
In a slightly more general form
|
||||
an interface <code>T</code> may use a (possibly qualified) interface type
|
||||
name <code>E</code> as an interface element. This is called
|
||||
<i>embedding</i> interface <code>E</code> in <code>T</code>.
|
||||
The <a href="#Method_sets">method set</a> of <code>T</code> is the <i>union</i>
|
||||
of the method sets of <code>T</code>’s explicitly declared methods and of
|
||||
<code>T</code>’s embedded interfaces.
|
||||
The type set of <code>T</code> is the <i>intersection</i> of the type sets
|
||||
defined by <code>T</code>'s explicitly declared methods and the type sets
|
||||
of <code>T</code>’s embedded interfaces.
|
||||
In other words, the type set of <code>T</code> is the set of all types that implement all the
|
||||
explicitly declared methods of <code>T</code> and also all the methods of
|
||||
<code>E</code>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -1361,8 +1402,7 @@ type ReadWriter interface {
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
A <i>union</i> of method sets contains the (exported and non-exported)
|
||||
methods of each method set exactly once, and methods with the
|
||||
When embedding interfaces, methods with the
|
||||
<a href="#Uniqueness_of_identifiers">same</a> names must
|
||||
have <a href="#Type_identity">identical</a> signatures.
|
||||
</p>
|
||||
|
@ -1374,6 +1414,134 @@ type ReadCloser interface {
|
|||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Finally, in their most general form, an interface element may be an arbitrary type
|
||||
<code>T</code>, a type term of the form <code>~T</code>, or a union of type terms
|
||||
<code>T1 | T2 | … Tn</code>.
|
||||
Together with method specifications, these elements enable the precise
|
||||
definition of an interface's type set as follows:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>The type set of the empty interface is the set of all types.
|
||||
</li>
|
||||
|
||||
<li>The type set of a non-empty interface is the intersection of the type sets
|
||||
of its interface elements.
|
||||
</li>
|
||||
|
||||
<li>The type set of a method specification is the set of types
|
||||
whose method sets include that method.
|
||||
</li>
|
||||
|
||||
<li>The type set of a non-interface type is the set consisting
|
||||
of just that type.
|
||||
</li>
|
||||
|
||||
<li>The type set of a term of the form <code>~T</code>
|
||||
is the set of types whose underlying type is <code>T</code>.
|
||||
</li>
|
||||
|
||||
<li>The type set of a <i>union</i> of terms <code>T1 | T2 | … Tn</code>
|
||||
is the union of the type sets of the terms.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<pre>
|
||||
// An interface representing only the type int.
|
||||
interface {
|
||||
int
|
||||
}
|
||||
|
||||
// An interface representing all types with underlying type int.
|
||||
interface {
|
||||
~int
|
||||
}
|
||||
|
||||
// An interface representing all types with underlying type int which implement the String method.
|
||||
interface {
|
||||
~int
|
||||
String() string
|
||||
}
|
||||
|
||||
// An interface representing an empty type set: there is no type that is both an int and a string.
|
||||
interface {
|
||||
int
|
||||
string
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
In a term of the form <code>~T</code>, the underlying type of <code>T</code>
|
||||
must be itself, and <code>T</code> cannot be an interface.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type MyInt int
|
||||
|
||||
interface {
|
||||
~[]byte // the underlying type of []byte is itself
|
||||
~MyInt // illegal: the underlying type of MyInt is not MyInt
|
||||
~error // illegal: error is an interface
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Union expressions denote unions of type sets:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// The Floats interface represents all floating-point types
|
||||
// (including any named types whose underlying types are
|
||||
// either float32 or float64).
|
||||
type Floats interface {
|
||||
~float32 | ~float64
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
In a union expression, a term cannot be a type parameter, and the type sets of all
|
||||
non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty).
|
||||
Given a type parameter <code>P</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
interface {
|
||||
P // illegal: the term P is a type parameter
|
||||
int | P // illegal: the term P is a type parameter
|
||||
~int | MyInt // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
|
||||
float32 | Floats // overlapping type sets but Floats is an interface
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Implementation restriction:
|
||||
A union expression with more than one term cannot contain interface types
|
||||
with non-empty <a href="#Method_sets">method sets</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Interfaces that contain union or tilde terms (not just methods) may only be used
|
||||
as type constraints, or as elements of other interfaces used as constraints. They
|
||||
cannot be the types of values or variables, or components of other, non-interface types.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var x Floats // illegal: Floats is restricted by float32 and float64
|
||||
|
||||
var x interface{} = Floats(nil) // illegal
|
||||
|
||||
type Floatish struct {
|
||||
f Floats // illegal
|
||||
}
|
||||
</pre>
|
||||
|
||||
<!-- TODO The rule below needs to be generalized to interface elements.
|
||||
It should be factored out and generalized to other types
|
||||
such as arrays and structs which are currently missing such a
|
||||
rule. See also #5069.
|
||||
-->
|
||||
|
||||
<p>
|
||||
An interface type <code>T</code> may not embed itself
|
||||
or any interface type that embeds <code>T</code>, recursively.
|
||||
|
@ -1872,7 +2040,8 @@ The following identifiers are implicitly declared in the
|
|||
</p>
|
||||
<pre class="grammar">
|
||||
Types:
|
||||
bool byte complex64 complex128 error float32 float64
|
||||
any bool byte comparable
|
||||
complex64 complex128 error float32 float64
|
||||
int int8 int16 int32 int64 rune string
|
||||
uint uint8 uint16 uint32 uint64 uintptr
|
||||
|
||||
|
|
Loading…
Reference in a new issue