From 434de2f8e9d3837711e0f853a2873cbb83325019 Mon Sep 17 00:00:00 2001
From: Robert Griesemer []B1
, B3
, and B4
i
The underlying type of P
is interface{}
.
-Each non-interface type T
has a core type, which is the same as the
-underlying type of T
.
-
-An interface T
has a core type if one of the following
-conditions is satisfied:
-
U
which is the underlying type
-of all types in the type set of T
; or
-T
contains only channel types
-with identical element type E
, and all directional channels have the same
-direction.
--No other interfaces have a core type. -
- --The core type of an interface is, depending on the condition that is satisfied, either: -
- -U
; or
-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.
--By definition, a core type is never a defined type, -type parameter, or -interface type. -
- --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 without 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 -- -
-Some operations (slice expressions,
-append
and copy
)
-rely on a slightly more loose form of core types which accept byte slices and strings.
-Specifically, if there are exactly two types, []byte
and string
,
-which are the underlying types of all types in the type set of interface T
,
-the core type of T
is called bytestring
.
-
-Examples of interfaces with bytestring
core types:
-
-interface{ int } // int (same as ordinary core type) -interface{ []byte | string } // bytestring -interface{ ~[]byte | myString } // bytestring -- -
-Note that bytestring
is not a real type; it cannot be used to declare
-variables or compose other types. It exists solely to describe the behavior of some
-operations that read from a sequence of bytes, which may be a byte slice or a string.
-
-Two types are either identical or different. +Two types are either identical ("the same") or different.
@@ -3253,7 +3153,8 @@ math.Sin // denotes the Sin function in package math
-Composite literals construct new composite values each time they are evaluated. +Composite literals construct new values for structs, arrays, slices, and maps +each time they are evaluated. They consist of the type of the literal followed by a brace-bound list of elements. Each element may optionally be preceded by a corresponding key.
@@ -3271,10 +3172,14 @@ Element = Expression | LiteralValue .
-The LiteralType's core type T
+Unless the LiteralType is a type parameter,
+its underlying type
must be a struct, array, slice, or map type
(the syntax enforces this constraint except when the type is given
as a TypeName).
+If the LiteralType is a type parameter, all types in its type set
+must have the same underlying type which must be
+a valid composite literal type.
The types of the elements and keys must be assignable
to the respective field, element, and key types of type T
;
there is no additional conversion.
@@ -3459,7 +3364,6 @@ noteFrequency := map[string]float32{
}
-
@@ -3932,11 +3836,12 @@ The following rules apply:
-If a
is neither a map nor a type parameter:
+If a
is neither a map nor a type parameter:
x
must be an untyped constant or its
- core type must be an integerx
must be an untyped constant, or its type must be
+ an integer or a type parameter whose type set
+ contains only integer typesint
int
nil
map causes a
Slice expressions construct a substring or slice from a string, array, pointer -to array, or slice. There are two variants: a simple form that specifies a low +to array, or slice operand. +There are two variants: a simple form that specifies a low and high bound, and a full form that also specifies a bound on the capacity.
+
+If the operand type is a type parameter,
+unless its type set contains string types,
+all types in the type set must have the same underlying type, and the slice expression
+must be valid for an operand of that type.
+If the type set contains string types it may also contain byte slices with underlying
+type []byte
.
+In this case, the slice expression must be valid for an operand of string
+type.
+
-The primary expression
+For a string, array, pointer to array, or slice a
, the primary expression
@@ -4065,9 +3982,7 @@ a[low : high]
-constructs a substring or slice. The core type of
-a
must be a string, array, pointer to array, slice, or a
-bytestring
.
+constructs a substring or slice.
The indices low
and
high
select which elements of operand a
appear
in the result. The result has indices starting at 0 and length equal to
@@ -4147,7 +4062,7 @@ s3 := s[:0] // s3 == nil
-The primary expression
+For an array, pointer to array, or slice a
(but not a string), the primary expression
@@ -4158,8 +4073,6 @@ a[low : high : max] constructs a slice of the same type, and with the same length and elements as the simple slice expressiona[low : high]
. Additionally, it controls the resulting slice's capacity by setting it tomax - low
. Only the first index may be omitted; it defaults to 0. -The core type ofa
must be an array, pointer to array, -or slice (but not a string). After slicing the arraya
@@ -4265,8 +4178,8 @@ No run-time panic occurs in this case.Calls
-Given an expression
f
with a core type -F
of function type, +Given an expressionf
of function type +F
,@@ -4296,6 +4209,12 @@ Iff
denotes a generic function, it must be or used as a function value. ++If the type of
+f
is a type parameter, +all types in its type set must have the same underlying type, which must be a function type, +and the function call must be valid for that type. +In a function call, the function value and arguments are evaluated in the usual order. @@ -4809,17 +4728,28 @@ more complicated:
C
has a core type
- core(C)
+ If all types in C
's type set have the same
+ underlying type U
,
and P
has a known type argument A
,
- core(C)
and A
must unify loosely.
+ U
and A
must unify loosely.
+C
's type set are
+ channel types with the same element type and non-conflicting
+ channel directions,
+ and P
has a known type argument A
,
+ the most restrictive channel type in C
's type
+ set and A
must unify loosely.
+P
does not have a known type argument
and C
contains exactly one type term T
that is not an underlying (tilde) type, unification adds the
mapping P ➞ T
to the map.
C
does not have a core type
+ If C
does not have a type U
+ as described above
and P
has a known type argument A
,
A
must have all methods of C
, if any,
and corresponding method types must unify exactly.
@@ -5370,10 +5300,10 @@ var x *int = nil
-For an operand ch
whose core type is a
-channel,
+For an operand ch
of channel type,
the value of the receive operation <-ch
is the value received
-from the channel ch
. The channel direction must permit receive operations,
+from the channel ch
.
+The channel direction must permit receive operations,
and the type of the receive operation is the element type of the channel.
The expression blocks until a value is available.
Receiving from a nil
channel blocks forever.
@@ -5389,6 +5319,12 @@ f(<-ch)
<-strobe // wait until clock pulse and discard received value
+
+If the operand type is a type parameter, +all types in its type set must be channel types that permit receive operations, and +they must all have the same element type, which is the type of the receive operation. +
+A receive expression used in an assignment statement or initialization of the special form
@@ -6124,8 +6060,7 @@ len("foo") // illegal if len is the built-in function
A send statement sends a value on a channel.
-The channel expression's core type
-must be a channel,
+The channel expression must be of channel type,
the channel direction must permit send operations,
and the type of the value to be sent must be assignable
to the channel's element type.
@@ -6149,6 +6084,13 @@ A send on a nil
channel blocks forever.
ch <- 3 // send value 3 to channel ch
+
+If the type of the channel expression is a +type parameter, +all types in its type set must be channel types that permit send operations, +they must all have the same element type, +and the type of the value to be sent must be assignable to that element type. +
The expression on the right in the "range" clause is called the range expression, -its core type must be -an array, pointer to an array, slice, string, map, channel permitting +which may be an array, pointer to an array, slice, string, map, channel permitting receive operations, an integer, or a function with specific signature (see below). As with an assignment, if present the operands on the left must be @@ -6956,6 +6897,12 @@ for k, v := range t.Walk { } +
+If the type of the range expression is a type parameter, +all types in its type set must have the same underlying type and the range expression must be valid +for that type, or, if the type set contains channel types, it must only contain channel types with +identical element types, and all channel types must permit receive operations. +
The variadic function append
-appends zero or more values x
to a slice s
-and returns the resulting slice of the same type as s
.
-The core type of s
must be a slice
-of type []E
.
+appends zero or more values x
to a slice s
of
+type S
and returns the resulting slice, also of type
+S
.
The values x
are passed to a parameter of type ...E
+where E
is the element type of S
and the respective parameter
passing rules apply.
-As a special case, if the core type of s
is []byte
,
-append
also accepts a second argument with core type
-bytestring
followed by ...
.
-This form appends the bytes of the byte slice or string.
+As a special case, append
also accepts a first argument assignable
+to type []byte
with a second argument of string type followed by
+...
.
+This form appends the bytes of the string.
-append(s S, x ...E) S // core type of S is []E +append(s S, x ...E) S // E is the element type of S+
+If S
is a type parameter,
+all types in its type set must have the same underlying slice type []E
.
+
If the capacity of s
is not large enough to fit the additional
values, append
allocates a new, sufficiently large underlying
@@ -7471,14 +7423,14 @@ b = append(b, "bar"...) // append string contents b is []byte{'b
The function copy
copies slice elements from
a source src
to a destination dst
and returns the
number of elements copied.
-The core types of both arguments must be slices
-with identical element type.
+Both arguments must have identical element type
+E
and must be assignable to a slice of type []E
.
The number of elements copied is the minimum of
len(src)
and len(dst)
.
-As a special case, if the destination's core type is []byte
,
-copy
also accepts a source argument with core type
-bytestring
.
-This form copies the bytes from the byte slice or string into the byte slice.
+As a special case, copy
also accepts a destination argument
+assignable to type []byte
with a source argument of a
+string
type.
+This form copies the bytes from the string into the byte slice.
@@ -7486,6 +7438,11 @@ copy(dst, src []T) int copy(dst []byte, src string) int+
+If the type of one or both arguments is a type parameter,
+all types in their respective type sets must have the same underlying slice type []E
.
+
Examples:
@@ -7536,8 +7493,7 @@ If the map or slice isnil
, clear
is a no-op.
-For an argument ch
with a core type
-that is a channel, the built-in function close
+For a channel ch
, the built-in function close(ch)
records that no more values will be sent on the channel.
It is an error if ch
is a receive-only channel.
Sending to or closing a closed channel causes a run-time panic.
@@ -7549,6 +7505,12 @@ The multi-valued receive operation
returns a received value along with an indication of whether the channel is closed.
+If the type of the argument to close
is a
+type parameter,
+all types in its type set must be channels with the same element type.
+It is an error if any of those channels is a receive-only channel.
+
The built-in function make
takes a type T
,
+which must be a slice, map or channel type, or a type parameter,
optionally followed by a type-specific list of expressions.
-The core type of T
must
-be a slice, map or channel.
It returns a value of type T
(not *T
).
The memory is initialized as described in the section on
initial values.
-Call Core type Result +Call Type T Result -make(T, n) slice slice of type T with length n and capacity n -make(T, n, m) slice slice of type T with length n and capacity m +make(T, n) slice slice of type T with length n and capacity n +make(T, n, m) slice slice of type T with length n and capacity m -make(T) map map of type T -make(T, n) map map of type T with initial space for approximately n elements +make(T) map map of type T +make(T, n) map map of type T with initial space for approximately n elements -make(T) channel unbuffered channel of type T -make(T, n) channel buffered channel of type T, buffer size n +make(T) channel unbuffered channel of type T +make(T, n) channel buffered channel of type T, buffer size n + +make(T, n) type parameter see below +make(T, n, m) type parameter see below+
+If the first argument is a type parameter, +all types in its type set must have the same underlying type, which must be a slice +or map type, or, if there are channel types, there must only be channel types, they +must all have the same element type, and the channel directions must not conflict. +
+
Each of the size arguments n
and m
must be of integer type,
have a type set containing only integer types,
@@ -8481,17 +8452,14 @@ func String(ptr *byte, len IntegerType) string
func StringData(str string) *byte
-
-
A Pointer
is a pointer type but a Pointer
value may not be dereferenced.
-Any pointer or value of core type uintptr
can be
-converted to a type of core type Pointer
and vice versa.
+Any pointer or value of underlying type uintptr
can be
+converted to a type of underlying type Pointer
and vice versa.
+If the respective types are type parameters, all types in
+their respective type sets must have the same underlying type, which must be uintptr
and
+Pointer
, respectively.
The effect of converting between Pointer
and uintptr
is implementation-defined.
≡A
+ type parameter, and all the types in its type set unify with
+ the other type
+ per the unification rules for ≡A
(loose unification at the top level and exact unification
for element types).