From 56c9b51b937cca7d3db517add96bd9517bbffb80 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 2 Feb 2017 15:43:56 -0800 Subject: [PATCH] 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/36213 Reviewed-by: Rob Pike --- doc/go_spec.html | 159 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 109 insertions(+), 50 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index c71126d25d..7f25fff137 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -685,11 +685,9 @@ If a variable has not yet been assigned a value, its value is the

Types

-A type determines the set of values and operations specific to values of that -type. Types may be named or unnamed. Named types are specified -by a (possibly qualified) -type name; unnamed types are specified -using a type literal, which composes a new type from existing types. +A type determines a set of values together with operations and methods specific +to those values. A type may be denoted by a type name, if it has one, +or specified using a type literal, which composes a type from existing types.

@@ -702,6 +700,7 @@ TypeLit   = ArrayType | StructType | PointerType | FunctionType | InterfaceType
 

Named instances of the boolean, numeric, and string types are predeclared. +Other named types are introduced with type declarations. Composite types—array, struct, pointer, function, interface, slice, map, and channel types—may be constructed using type literals. @@ -717,16 +716,23 @@ is the underlying type of the type to which T refers in its

-   type T1 string
-   type T2 T1
-   type T3 []T1
-   type T4 T3
+type (
+	A1 = string
+	A2 = A1
+)
+
+type (
+	B1 string
+	B2 B1
+	B3 []B1
+	B4 B3
+)
 

-The underlying type of string, T1, and T2 -is string. The underlying type of []T1, T3, -and T4 is []T1. +The underlying type of string, A1, A2, B1, +and B2 is string. +The underlying type of []B1, B3, and B4 is []B1.

Method sets

@@ -1417,11 +1423,10 @@ Two types are either identical or different.

-Two named types are identical if their type names originate in the same -TypeSpec. -A named and an unnamed type are always different. Two unnamed types are identical -if the corresponding type literals are identical, that is, if they have the same -literal structure and corresponding components have identical types. In detail: +A defined type is always different from any other type. +Otherwise, two types are identical if their underlying type literals are +structurally equivalent; that is, they have the same literal structure and corresponding +components have identical types. In detail:

    @@ -1460,13 +1465,24 @@ Given the declarations
     type (
    -	T0 []string
    -	T1 []string
    -	T2 struct{ a, b int }
    -	T3 struct{ a, c int }
    -	T4 func(int, float64) *T0
    -	T5 func(x int, y float64) *[]string
    +	A0 = []string
    +	A1 = A0
    +	A2 = struct{ a, b int }
    +	A3 = int
    +	A4 = func(A3, float64) *A0
    +	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
     

    @@ -1474,17 +1490,22 @@ these types are identical:

    -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
     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
     

    -T0 and T1 are different because they are named types -with distinct declarations; func(int, float64) *T0 and -func(x int, y float64) *[]string are different because T0 -is different from []string. +B0 and B1 are different because they are new types +created by distinct type definitions; +func(int, float64) *B0 and func(x int, y float64) *[]string +are different because B0 is different from []string.

    @@ -1502,7 +1523,7 @@ A value x is assignable to a variable x's type V and T have identical underlying types and at least one of V -or T is not a named type. +or T is not a defined type.
  • T is an interface type and @@ -1511,7 +1532,7 @@ or T is not a named type.
  • x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, -and at least one of V or T is not a named type. +and at least one of V or T is not a defined type.
  • x is the predeclared identifier nil and T @@ -1840,23 +1861,60 @@ last non-empty expression list.

    Type declarations

    -A type declaration binds an identifier, the type name, to a new type -that has the same underlying type as an existing type, -and operations defined for the existing type are also defined for the new type. -The new type is different from the existing type. +A type declaration binds an identifier, the type name, to a type. +Type declarations come in two forms: Alias declarations and type definitions. +

    + +

    +TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
    +TypeSpec = AliasDecl | TypeDef .
    +
    + +

    Alias declarations

    + +

    +An alias declaration binds an identifier to the given type.

    -TypeDecl     = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
    -TypeSpec     = identifier Type .
    +AliasDecl = identifier "=" Type .
     
    +

    +Within the scope of +the identifier, it serves as an alias for the type. +

    +
    -type IntArray [16]int
    +type (
    +	nodeList = []*Node  // nodeList and []*Node are identical types
    +	Polar    = polar    // Polar and polar denote identical types
    +)
    +
    + +

    Type definitions

    + +

    +A type definition binds an identifier to a newly created type +with the same underlying type and +operations as the given type. +

    + +
    +TypeDef = identifier Type .
    +
    + +

    +The new type is called a defined type. +It is different from any other type, +including the type it is created from. +

    + +
     type (
    -	Point struct{ x, y float64 }
    -	Polar Point
    +	Point struct{ x, y float64 }  // Point and struct{ x, y float64 } are different types
    +	polar Point                   // polar and Point denote different types
     )
     
     type TreeNode struct {
    @@ -1872,8 +1930,9 @@ type Block interface {
     

    -The declared type does not inherit any methods -bound to the existing type, but the method set +A defined type may have methods associated with it. +It does not inherit any methods bound to the given type, +but the method set of an interface type or of elements of a composite type remains unchanged:

    @@ -1901,8 +1960,8 @@ type MyBlock Block

-A type declaration may be used to define a different boolean, numeric, or string -type and attach methods to it: +Type definitions may be used to define different boolean, numeric, +or string types and associate methods with them:

@@ -1924,8 +1983,8 @@ func (tz TimeZone) String() string {
 

Variable declarations

-A variable declaration creates one or more variables, binds corresponding -identifiers to them, and gives each a type and an initial value. +A variable declaration creates one or more variables, +binds corresponding identifiers to them, and gives each a type and an initial value.

@@ -2083,8 +2142,8 @@ and associates the method with the receiver's base type.
 

-MethodDecl   = "func" Receiver MethodName ( Function | Signature ) .
-Receiver     = Parameters .
+MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
+Receiver   = Parameters .
 

@@ -2093,7 +2152,7 @@ name. That parameter section must declare a single non-variadic parameter, the r Its type must be of the form T or *T (possibly using parentheses) where T is a type name. The type denoted by T is called the receiver base type; it must not be a pointer or interface type and -it must be declared in the same package as the method. +it must be defined in the same package as the method. The method is said to be bound to the base type and the method name is visible only within selectors for type T or *T. -- 2.48.1