Commit 56c9b51b authored by Robert Griesemer's avatar Robert Griesemer

spec: introduce alias declarations and type definitions

To avoid confusion caused by the term "named type" (which now just
means a type with a name, but formerly meant a type declared with
a non-alias type declaration), a type declaration now comes in two
forms: alias declarations and type definitions. Both declare a type
name, but type definitions also define new types.

Replace the use of "named type" with "defined type" elsewhere in
the spec.

For #18130.

Change-Id: I49f5ddacefce90354eb65ee5fbf10ba737221995
Reviewed-on: https://go-review.googlesource.com/36213Reviewed-by: default avatarRob Pike <r@golang.org>
parent 3b68a647
<!--{ <!--{
"Title": "The Go Programming Language Specification", "Title": "The Go Programming Language Specification",
"Subtitle": "Version of January 31, 2017", "Subtitle": "Version of February 3, 2017",
"Path": "/ref/spec" "Path": "/ref/spec"
}--> }-->
...@@ -685,11 +685,9 @@ If a variable has not yet been assigned a value, its value is the ...@@ -685,11 +685,9 @@ If a variable has not yet been assigned a value, its value is the
<h2 id="Types">Types</h2> <h2 id="Types">Types</h2>
<p> <p>
A type determines the set of values and operations specific to values of that A type determines a set of values together with operations and methods specific
type. Types may be <i>named</i> or <i>unnamed</i>. Named types are specified to those values. A type may be denoted by a <i>type name</i>, if it has one,
by a (possibly <a href="#Qualified_identifiers">qualified</a>) or specified using a <i>type literal</i>, which composes a type from existing types.
<a href="#Type_declarations"><i>type name</i></a>; unnamed types are specified
using a <i>type literal</i>, which composes a new type from existing types.
</p> </p>
<pre class="ebnf"> <pre class="ebnf">
...@@ -702,6 +700,7 @@ TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType ...@@ -702,6 +700,7 @@ TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType
<p> <p>
Named instances of the boolean, numeric, and string types are Named instances of the boolean, numeric, and string types are
<a href="#Predeclared_identifiers">predeclared</a>. <a href="#Predeclared_identifiers">predeclared</a>.
Other named types are introduced with <a href="#Type_declarations">type declarations</a>.
<i>Composite types</i>&mdash;array, struct, pointer, function, <i>Composite types</i>&mdash;array, struct, pointer, function,
interface, slice, map, and channel types&mdash;may be constructed using interface, slice, map, and channel types&mdash;may be constructed using
type literals. type literals.
...@@ -717,16 +716,23 @@ is the underlying type of the type to which <code>T</code> refers in its ...@@ -717,16 +716,23 @@ is the underlying type of the type to which <code>T</code> refers in its
</p> </p>
<pre> <pre>
type T1 string type (
type T2 T1 A1 = string
type T3 []T1 A2 = A1
type T4 T3 )
type (
B1 string
B2 B1
B3 []B1
B4 B3
)
</pre> </pre>
<p> <p>
The underlying type of <code>string</code>, <code>T1</code>, and <code>T2</code> The underlying type of <code>string</code>, <code>A1</code>, <code>A2</code>, <code>B1</code>,
is <code>string</code>. The underlying type of <code>[]T1</code>, <code>T3</code>, and <code>B2</code> is <code>string</code>.
and <code>T4</code> is <code>[]T1</code>. The underlying type of <code>[]B1</code>, <code>B3</code>, and <code>B4</code> is <code>[]B1</code>.
</p> </p>
<h3 id="Method_sets">Method sets</h3> <h3 id="Method_sets">Method sets</h3>
...@@ -1417,11 +1423,10 @@ Two types are either <i>identical</i> or <i>different</i>. ...@@ -1417,11 +1423,10 @@ Two types are either <i>identical</i> or <i>different</i>.
</p> </p>
<p> <p>
Two <a href="#Types">named types</a> are identical if their type names originate in the same A <a href="#Type_definitions">defined type</a> is always different from any other type.
<a href="#Type_declarations">TypeSpec</a>. Otherwise, two types are identical if their <a href="#Types">underlying</a> type literals are
A named and an <a href="#Types">unnamed type</a> are always different. Two unnamed types are identical structurally equivalent; that is, they have the same literal structure and corresponding
if the corresponding type literals are identical, that is, if they have the same components have identical types. In detail:
literal structure and corresponding components have identical types. In detail:
</p> </p>
<ul> <ul>
...@@ -1460,13 +1465,24 @@ Given the declarations ...@@ -1460,13 +1465,24 @@ Given the declarations
<pre> <pre>
type ( type (
T0 []string A0 = []string
T1 []string A1 = A0
T2 struct{ a, b int } A2 = struct{ a, b int }
T3 struct{ a, c int } A3 = int
T4 func(int, float64) *T0 A4 = func(A3, float64) *A0
T5 func(x int, y float64) *[]string A5 = func(x int, _ float64) *[]string
) )
type (
B0 A0
B1 []string
B2 struct{ a, b int }
B3 struct{ a, c int }
B4 func(int, float64) *B0
B5 func(x int, y float64) *A1
)
type C0 = B0
</pre> </pre>
<p> <p>
...@@ -1474,17 +1490,22 @@ these types are identical: ...@@ -1474,17 +1490,22 @@ these types are identical:
</p> </p>
<pre> <pre>
T0 and T0 A0, A1, and []string
A2 and struct{ a, b int }
A3 and int
A4, func(int, float64) *[]string, and A5
B0, B0, and C0
[]int and []int []int and []int
struct{ a, b *T5 } and struct{ a, b *T5 } struct{ a, b *T5 } and struct{ a, b *T5 }
func(x int, y float64) *[]string and func(int, float64) (result *[]string) func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5
</pre> </pre>
<p> <p>
<code>T0</code> and <code>T1</code> are different because they are named types <code>B0</code> and <code>B1</code> are different because they are new types
with distinct declarations; <code>func(int, float64) *T0</code> and created by distinct <a href="#Type_definitions">type definitions</a>;
<code>func(x int, y float64) *[]string</code> are different because <code>T0</code> <code>func(int, float64) *B0</code> and <code>func(x int, y float64) *[]string</code>
is different from <code>[]string</code>. are different because <code>B0</code> is different from <code>[]string</code>.
</p> </p>
...@@ -1502,7 +1523,7 @@ A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</ ...@@ -1502,7 +1523,7 @@ A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</
<li> <li>
<code>x</code>'s type <code>V</code> and <code>T</code> have identical <code>x</code>'s type <code>V</code> and <code>T</code> have identical
<a href="#Types">underlying types</a> and at least one of <code>V</code> <a href="#Types">underlying types</a> and at least one of <code>V</code>
or <code>T</code> is not a <a href="#Types">named type</a>. or <code>T</code> is not a <a href="#Type_definitions">defined</a> type.
</li> </li>
<li> <li>
<code>T</code> is an interface type and <code>T</code> is an interface type and
...@@ -1511,7 +1532,7 @@ or <code>T</code> is not a <a href="#Types">named type</a>. ...@@ -1511,7 +1532,7 @@ or <code>T</code> is not a <a href="#Types">named type</a>.
<li> <li>
<code>x</code> is a bidirectional channel value, <code>T</code> is a channel type, <code>x</code> is a bidirectional channel value, <code>T</code> is a channel type,
<code>x</code>'s type <code>V</code> and <code>T</code> have identical element types, <code>x</code>'s type <code>V</code> and <code>T</code> have identical element types,
and at least one of <code>V</code> or <code>T</code> is not a named type. and at least one of <code>V</code> or <code>T</code> is not a defined type.
</li> </li>
<li> <li>
<code>x</code> is the predeclared identifier <code>nil</code> and <code>T</code> <code>x</code> is the predeclared identifier <code>nil</code> and <code>T</code>
...@@ -1840,23 +1861,60 @@ last non-empty expression list. ...@@ -1840,23 +1861,60 @@ last non-empty expression list.
<h3 id="Type_declarations">Type declarations</h3> <h3 id="Type_declarations">Type declarations</h3>
<p> <p>
A type declaration binds an identifier, the <i>type name</i>, to a new type A type declaration binds an identifier, the <i>type name</i>, to a <a href="#Types">type</a>.
that has the same <a href="#Types">underlying type</a> as an existing type, Type declarations come in two forms: Alias declarations and type definitions.
and operations defined for the existing type are also defined for the new type. <p>
The new type is <a href="#Type_identity">different</a> from the existing type.
<pre class="ebnf">
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
TypeSpec = AliasDecl | TypeDef .
</pre>
<h4 id="Alias_declarations">Alias declarations</h4>
<p>
An alias declaration binds an identifier to the given type.
</p> </p>
<pre class="ebnf"> <pre class="ebnf">
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) . AliasDecl = identifier "=" Type .
TypeSpec = identifier Type .
</pre> </pre>
<p>
Within the <a href="#Declarations_and_scope">scope</a> of
the identifier, it serves as an <i>alias</i> for the type.
</p>
<pre> <pre>
type IntArray [16]int type (
nodeList = []*Node // nodeList and []*Node are identical types
Polar = polar // Polar and polar denote identical types
)
</pre>
<h4 id="Type_definitions">Type definitions</h4>
<p>
A type definition binds an identifier to a newly created type
with the same <a href="#Types">underlying type</a> and
operations as the given type.
</p>
<pre class="ebnf">
TypeDef = identifier Type .
</pre>
<p>
The new type is called a <i>defined type</i>.
It is <a href="#Type_identity">different</a> from any other type,
including the type it is created from.
</p>
<pre>
type ( type (
Point struct{ x, y float64 } Point struct{ x, y float64 } // Point and struct{ x, y float64 } are different types
Polar Point polar Point // polar and Point denote different types
) )
type TreeNode struct { type TreeNode struct {
...@@ -1872,8 +1930,9 @@ type Block interface { ...@@ -1872,8 +1930,9 @@ type Block interface {
</pre> </pre>
<p> <p>
The declared type does not inherit any <a href="#Method_declarations">methods</a> A defined type may have <a href="#Method_declarations">methods</a> associated with it.
bound to the existing type, but the <a href="#Method_sets">method set</a> It does not inherit any methods bound to the given type,
but the <a href="#Method_sets">method set</a>
of an interface type or of elements of a composite type remains unchanged: of an interface type or of elements of a composite type remains unchanged:
</p> </p>
...@@ -1901,8 +1960,8 @@ type MyBlock Block ...@@ -1901,8 +1960,8 @@ type MyBlock Block
</pre> </pre>
<p> <p>
A type declaration may be used to define a different boolean, numeric, or string Type definitions may be used to define different boolean, numeric,
type and attach methods to it: or string types and associate methods with them:
</p> </p>
<pre> <pre>
...@@ -1924,8 +1983,8 @@ func (tz TimeZone) String() string { ...@@ -1924,8 +1983,8 @@ func (tz TimeZone) String() string {
<h3 id="Variable_declarations">Variable declarations</h3> <h3 id="Variable_declarations">Variable declarations</h3>
<p> <p>
A variable declaration creates one or more variables, binds corresponding A variable declaration creates one or more <a href="#Variables">variables</a>,
identifiers to them, and gives each a type and an initial value. binds corresponding identifiers to them, and gives each a type and an initial value.
</p> </p>
<pre class="ebnf"> <pre class="ebnf">
...@@ -2083,8 +2142,8 @@ and associates the method with the receiver's <i>base type</i>. ...@@ -2083,8 +2142,8 @@ and associates the method with the receiver's <i>base type</i>.
</p> </p>
<pre class="ebnf"> <pre class="ebnf">
MethodDecl = "func" Receiver MethodName ( Function | Signature ) . MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
Receiver = Parameters . Receiver = Parameters .
</pre> </pre>
<p> <p>
...@@ -2093,7 +2152,7 @@ name. That parameter section must declare a single non-variadic parameter, the r ...@@ -2093,7 +2152,7 @@ name. That parameter section must declare a single non-variadic parameter, the r
Its type must be of the form <code>T</code> or <code>*T</code> (possibly using Its type must be of the form <code>T</code> or <code>*T</code> (possibly using
parentheses) where <code>T</code> is a type name. The type denoted by <code>T</code> is called parentheses) where <code>T</code> is a type name. The type denoted by <code>T</code> is called
the receiver <i>base type</i>; it must not be a pointer or interface type and the receiver <i>base type</i>; it must not be a pointer or interface type and
it must be declared in the same package as the method. it must be <a href="#Type_definitions">defined</a> in the same package as the method.
The method is said to be <i>bound</i> to the base type and the method name The method is said to be <i>bound</i> to the base type and the method name
is visible only within <a href="#Selectors">selectors</a> for type <code>T</code> is visible only within <a href="#Selectors">selectors</a> for type <code>T</code>
or <code>*T</code>. or <code>*T</code>.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment