From 99b61be9f573ca46f4a4160e536abcb62180638a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 9 Feb 2022 17:36:51 -0800 Subject: [PATCH] spec: move all sections describing type properties into one place This change only shuffles sections for better organization; there are no other changes except title and link adjustments. Until now, the sections on underlying types and method sets were immediately following the introduction of types. As it becomes necessary to introduce the notion of a core type more centrally, the natural place is immediately following the section on underlying types. All together, these sections, immediately after the introduction of types, would distract from purpose of the section on types, which is to introduce the various types that Go offers. The more natural place for the definition of underlying, core, and specific types is the section on properties of types and values. To accomplish this, the section on the structure of interfaces is split into a section on core types and one on specific types, and the various sections are reorganized appropriately. The new organization of the section on types now simply introduces all Go types as follows: - boolean types - numeric types - string types - array types - slice types - struct types - pointer types - function types - interface types - map types - channel types - type parameters The new organization of the section on properties of types and values is as follows: - underlying types - core types - specific types - type identity - assignability - representability - method sets Change-Id: I59e4d47571da9d4c89d47d777f5353fb1c5843e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/384623 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot --- doc/go_spec.html | 377 ++++++++++++++++++++++++----------------------- 1 file changed, 192 insertions(+), 185 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 751d7fea01..99bedf2671 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -818,79 +818,6 @@ Predeclared types, defined types, and type parameters are called named types< An alias denotes a named type if the type given in the alias declaration is a named type.

-

Underlying types

- -

-Each type T has an underlying type: If T -is one of the predeclared boolean, numeric, or string types, or a type literal, -the corresponding underlying type is T itself. -Otherwise, T's underlying type is the underlying type of the -type to which T refers in its type -declaration. Accordingly, the underlying type of a type parameter is the -underlying type of its type constraint, which -is always an interface. -

- -
-type (
-	A1 = string
-	A2 = A1
-)
-
-type (
-	B1 string
-	B2 B1
-	B3 []B1
-	B4 B3
-)
-
-func f[P any](x P) { … }
-
- -

-The underlying type of string, A1, A2, B1, -and B2 is string. -The underlying type of []B1, B3, and B4 is []B1. -The underlying type of P is interface{}. -

- -

Method sets

- -

-The method set of a type determines the methods that can be -called on an operand of that type. -Every type has a (possibly empty) method set associated with it: -

- -
    -
  • The method set of a defined type T consists of all -methods declared with receiver type T. -
  • - -
  • -The method set of a pointer to a defined type T -(where T is neither a pointer nor an interface) -is the set of all methods declared with receiver *T or T. -
  • - -
  • The method set of an interface type is the intersection -of the method sets of each type in the interface's type set -(the resulting method set is usually just the set of declared methods in the interface). -
  • -
- -

-Further rules apply to structs (and pointer to structs) containing embedded fields, -as described in the section on struct types. -Any other type has an empty method set. -

- -

-In a method set, each method must have a -unique -non-blank method name. -

-

Boolean types

@@ -1748,6 +1675,171 @@ The properties of a type parameter are determined by its

Properties of types and values

+

Underlying types

+ +

+Each type T has an underlying type: If T +is one of the predeclared boolean, numeric, or string types, or a type literal, +the corresponding underlying type is T itself. +Otherwise, T's underlying type is the underlying type of the +type to which T refers in its type +declaration. The underlying type of a type parameter is the +underlying type of its type constraint, which +is always an interface. +

+ +
+type (
+	A1 = string
+	A2 = A1
+)
+
+type (
+	B1 string
+	B2 B1
+	B3 []B1
+	B4 B3
+)
+
+func f[P any](x P) { … }
+
+ +

+The underlying type of string, A1, A2, B1, +and B2 is string. +The underlying type of []B1, B3, and B4 is []B1. +The underlying type of P is interface{}. +

+ +

Core types

+ +

+Each non-interface type T has a core type, which is the +underlying type of T. +

+ +

+An interface T has a core type if one of the following +conditions is satisfied: +

+ +
    +
  1. +There is a single type U which is the underlying type +of all types in the type set of T; or +
  2. +
  3. +the type set of T contains only channel types +with identical element type E, and all directional channels have the same +direction. +
  4. +
+ +

+All other interfaces don't have a core type. +

+ +

+The core type of an interface is, depending on the condition that is satisfied, either: +

+ +
    +
  1. +the type U; or +
  2. +
  3. +the type chan E if T contains only bidirectional +channels, or the type chan<- E or <-chan E +depending on the direction of the directional channels present. +
  4. +
+ +

+Examples of interfaces with core types: +

+ +
+type Celsius float32
+type Kelvin  float32
+
+interface{ int }                          // int
+interface{ Celsius|Kelvin }               // float32
+interface{ ~chan int }                    // chan int
+interface{ ~chan int|~chan<- int }        // chan<- int
+interface{ ~[]*data; String() string }    // []*data
+
+ +

+Examples of interfaces whithout core types: +

+ +
+interface{}                               // no single underlying type
+interface{ Celsius|float64 }              // no single underlying type
+interface{ chan int | chan<- string }     // channels have different element types
+interface{ <-chan int | chan<- int }      // directional channels have different directions
+
+ +

Specific types

+ +

+An interface specification that contains type elements +defines a (possibly empty) set of specific types. +Loosely speaking, these are the types T that appear in the +interface definition in terms of the form T, ~T, +or in unions of such terms. +

+ +

+More precisely, for a given interface, the set of specific types corresponds to +the set 𝑅 of representative types of the interface, if 𝑅 is non-empty and finite. +Otherwise, if 𝑅 is empty or infinite, the interface has no specific types. +

+ +

+For a given interface, type element or type term, the set 𝑅 of representative types is defined as follows: +

+ +
    +
  • For an interface with no type elements, 𝑅 is the (infinite) set of all types. +
  • + +
  • For an interface with type elements, + 𝑅 is the intersection of the representative types of its type elements. +
  • + +
  • For a non-interface type term T or a term of the form ~T, + 𝑅 is the set consisting of the type T. +
  • + +
  • For a union of terms + t1|t2|…|tn, + 𝑅 is the union of the representative types of the terms. +
  • +
+ +

+An interface may have specific types even if its type set +is empty. +

+ +

+Examples of interfaces with their specific types: +

+ +
+interface{}                    // no specific types
+interface{ int }               // int
+interface{ ~string }           // string
+interface{ int|~string }       // int, string
+interface{ Celsius|Kelvin }    // Celsius, Kelvin
+interface{ float64|any }       // no specific types (union is all types)
+interface{ int; m() }          // int (but type set is empty because int has no method m)
+interface{ ~int; m() }         // int (but type set is infinite because many integer types have a method m)
+interface{ int; any }          // int
+interface{ int; string }       // no specific types (intersection is empty)
+
+

Type identity

@@ -1888,7 +1980,7 @@ by a value of type T.

Additionally, if x's type V or T are type parameters -with specific types, x +with specific types, x is assignable to a variable of type T if one of the following conditions applies:

@@ -1940,7 +2032,7 @@ are representable by values of T's component type (float32

-If T is a type parameter with specific types, +If T is a type parameter with specific types, x is representable by a value of type T if x is representable by a value of each specific type of T.

@@ -1972,128 +2064,43 @@ x T x is not representable by a value of T because 1e1000 float64 1e1000 overflows to IEEE +Inf after rounding -

Structure of interfaces

- -

-An interface specification which contains type elements -defines a (possibly empty) set of specific types. -Loosely speaking, these are the types T that appear in the -interface definition in terms of the form T, ~T, -or in unions of such terms. -

- -

-More precisely, for a given interface, the set of specific types corresponds to -the set 𝑅 of representative types of the interface, if 𝑅 is non-empty and finite. -Otherwise, if 𝑅 is empty or infinite, the interface has no specific types. -

+

Method sets

-For a given interface, type element or type term, the set 𝑅 of representative types is defined as follows: +The method set of a type determines the methods that can be +called on an operand of that type. +Every type has a (possibly empty) method set associated with it:

    -
  • For an interface with no type elements, 𝑅 is the (infinite) set of all types. -
  • - -
  • For an interface with type elements, - 𝑅 is the intersection of the representative types of its type elements. -
  • - -
  • For a non-interface type term T or a term of the form ~T, - 𝑅 is the set consisting of the type T. -
  • - -
  • For a union of terms - t1|t2|…|tn, - 𝑅 is the union of the representative types of the terms. -
  • -
- -

-An interface may have specific types even if its type set -is empty. -

- -

-Examples of interfaces with their specific types: -

- -
-type Celsius float32
-type Kelvin  float32
-
-interface{}                    // no specific types
-interface{ int }               // int
-interface{ ~string }           // string
-interface{ int|~string }       // int, string
-interface{ Celsius|Kelvin }    // Celsius, Kelvin
-interface{ float64|any }       // no specific types (union is all types)
-interface{ int; m() }          // int (but type set is empty because int has no method m)
-interface{ ~int; m() }         // int (but type set is infinite because many integer types have a method m)
-interface{ int; any }          // int
-interface{ int; string }       // no specific types (intersection is empty)
-
- -

-An interface T has a core type if one of the following -conditions is satisfied: -

- -
    -
  1. -There is a single type U which is the underlying type -of all types in the type set of T; or -
  2. -
  3. -the type set of T contains only channel types -with identical element type E, and all directional channels have the same -direction. +
  4. The method set of a defined type T consists of all +methods declared with receiver type T.
  5. -
-

-All other interfaces don't have a core type. -

- -

-The core type is, depending on the condition that is satisfied, either: -

- -
  1. -the type U; or +The method set of a pointer to a defined type T +(where T is neither a pointer nor an interface) +is the set of all methods declared with receiver *T or T.
  2. -
  3. -the type chan E if T contains only bidirectional -channels, or the type chan<- E or <-chan E -depending on the direction of the directional channels present. + +
  4. The method set of an interface type is the intersection +of the method sets of each type in the interface's type set +(the resulting method set is usually just the set of declared methods in the interface).
  5. -
+

-Examples of interfaces with core types: +Further rules apply to structs (and pointer to structs) containing embedded fields, +as described in the section on struct types. +Any other type has an empty method set.

-
-interface{ int }                          // int
-interface{ Celsius|Kelvin }               // float32
-interface{ ~chan int }                    // chan int
-interface{ ~chan int|~chan<- int }        // chan<- int
-interface{ ~[]*data; String() string }    // []*data
-
-

-Examples of interfaces whithout core types: +In a method set, each method must have a +unique +non-blank method name.

-
-interface{}                               // no single underlying type
-interface{ Celsius|float64 }              // no single underlying type
-interface{ chan int | chan<- string }     // channels have different element types
-interface{ <-chan int | chan<- int }      // directional channels have different directions
-
-

Blocks

@@ -3783,7 +3790,7 @@ For a of map type M: For a of type parameter type P:

    -
  • P must have specific types.
  • +
  • P must have specific types.
  • The index expression a[x] must be valid for values of all specific types of P.
  • The element types of all specific types of P must be identical. @@ -4513,7 +4520,7 @@ min(1.0, 2) // illegal: default type float64 (for 1.0) doesn't match default

    Constraint type inference infers type arguments by considering type constraints. If a type parameter P has a constraint with a -core type C, +core type C, unifying P with C may infer additional type arguments, either the type argument for P, or if that is already known, possibly the type arguments for type parameters @@ -4774,7 +4781,7 @@ The bitwise logical and shift operators apply to integers only.

    Excluding shifts, if the operand type is a type parameter, -it must have specific types, and the operator must +it must have specific types, and the operator must apply to each specific type. The operands are represented as values of the type argument that the type parameter is instantiated with, and the operation is computed @@ -5314,7 +5321,7 @@ in any of these cases:

    Additionally, if T or x's type V are type -parameters with specific types, x +parameters with specific types, x can also be converted to type T if one of the following conditions applies:

    @@ -7023,7 +7030,7 @@ cap(s) [n]T, *[n]T array length (== n)

    If the argument type is a type parameter P, -P must have specific types, and +P must have specific types, and the call len(e) (or cap(e) respectively) must be valid for each specific type of P. The result is the length (or capacity, respectively) of the argument whose type -- 2.48.1