22
22
1. [Struct Types](#struct-types)
23
23
1. [Tuple Types](#tuple-types)
24
24
1. [Function and Method Types](#function-and-method-types)
25
+ 1. [Alias Types](#alias-types)
25
26
1. [Named Types](#named-types)
26
27
1. [Interface Types](#interface-types)
28
+ 1. [TypeParam types](#typeparam-types)
29
+ 1. [Union types](#union-types)
27
30
1. [TypeAndValue](#typeandvalue)
28
31
1 . [ Selections] ( #selections )
29
32
1 . [ Ids] ( #ids )
@@ -103,9 +106,6 @@ type, or has an inappropriate type for its context; this is known as
103
106
_ type deduction_ .
104
107
Third, for every constant expression in the program, it determines the
105
108
value of that constant; this is known as _ constant evaluation_ .
106
-
107
-
108
-
109
109
Superficially, it appears that these three processes could be done
110
110
sequentially, in the order above, but perhaps surprisingly, they must
111
111
be done together.
@@ -115,9 +115,6 @@ Conversely, the type of an expression may depend on the value of a
115
115
constant, since array types contain constants.
116
116
As a result, type deduction and constant evaluation must be done
117
117
together.
118
-
119
-
120
-
121
118
As another example, we cannot resolve the identifier ` k ` in the composite
122
119
literal ` T{k: 0} ` until we know whether ` T ` is a struct type.
123
120
If it is, then ` k ` must be found among ` T ` 's fields.
@@ -264,7 +261,7 @@ Scope: package "cmd/hello" scope 0x820533590 {
264
261
265
262
A package's ` Path ` , such as ` "encoding/json" ` , is the string
266
263
by which import declarations identify it.
267
- It is unique within a ` $GOPATH ` workspace,
264
+ It is unique within a workspace,
268
265
and for published packages it must be globally unique.
269
266
270
267
@@ -282,7 +279,7 @@ which provides access to all the named entities or
282
279
[ _ objects_ ] ( #objects ) declared at package level.
283
280
` Imports ` returns the set of packages directly imported by this
284
281
one, and may be useful for computing dependencies
285
- ([ Initialization Order] ( #initialization-order ) ).
282
+ (see [ Initialization Order] ( #initialization-order ) ).
286
283
287
284
288
285
@@ -336,12 +333,8 @@ offset, though usually we just call its `String` method:
336
333
fmt.Println(fset.Position(obj.Pos())) // "hello.go:10:6"
337
334
338
335
339
- Not all objects carry position information.
340
- Since the file format for compiler export data ([ Imports] ( #imports ) )
341
- does not record position information, calling ` Pos ` on an object
342
- imported from such a file returns zero, also known as
343
- ` token.NoPos ` .
344
-
336
+ Objects for predeclared functions and types such as ` len ` and ` int `
337
+ do not have a valid (non-zero) position: ` !obj.Pos().IsValid() ` .
345
338
346
339
347
340
There are eight kinds of objects in the Go type checker.
@@ -367,14 +360,22 @@ possible types, and we commonly use a type switch to distinguish them.
367
360
| *Nil // predeclared nil
368
361
369
362
370
- ` Object ` s are canonical.
371
- That is, two ` Object ` s ` x ` and ` y ` denote the same
372
- entity if and only if ` x==y ` .
363
+
364
+ Objects are canonical.
365
+ That is, two Objects ` x ` and ` y ` denote the same entity if and only if ` x==y ` .
366
+ (This is generally true but beware that parameterized types complicate matters; see
367
+ https://github.com/golang/exp/tree/master/typeparams/example for details.)
368
+
373
369
Object identity is significant, and objects are routinely compared by
374
370
the addresses of the underlying pointers.
375
- Although a package-level object is uniquely identified by its name
376
- and enclosing package, for other objects there is no simple way to
377
- obtain a string that uniquely identifies it.
371
+ A package-level object (func/var/const/type) can be uniquely
372
+ identified by its name and enclosing package.
373
+ The [ ` golang.org/x/tools/go/types/objectpath ` ] ( https://pkg.go.dev/golang.org/x/tools/go/types/objectpath )
374
+ package defines a naming scheme for objects that are
375
+ [ exported] ( #imports ) from their package or are unexported but form part of the
376
+ type of an exported object.
377
+ But for most objects, including all function-local objects,
378
+ there is no simple way to obtain a string that uniquely identifies it.
378
379
379
380
380
381
@@ -409,18 +410,20 @@ And some kinds of objects have methods in addition to those required by the
409
410
410
411
411
412
` (*Func).Scope ` returns the [ lexical block] ( #scopes )
412
- containing the function's parameters, results,
413
+ containing the function's type parameters, parameters, results,
413
414
and other local declarations.
414
415
` (*Var).IsField ` distinguishes struct fields from ordinary
415
416
variables, and ` (*Var).Anonymous ` discriminates named fields like
416
417
the one in ` struct{T T} ` from anonymous fields like the one in ` struct{T} ` .
417
418
` (*Const).Val ` returns the value of a named [ constant] ( #constants ) .
418
419
419
420
420
- ` (*TypeName).IsAlias ` , introduced in Go 1.9, reports whether the
421
- type name is simply an alias for a type (as in ` type I = int ` ),
422
- as opposed to a definition of a [ ` Named ` ] ( #named-types ) type, as
423
- in ` type Celsius float64 ` .
421
+ ` (*TypeName).IsAlias ` reports whether the type name declares an alias
422
+ for an existing type (as in ` type I = int ` ), as opposed to defining a new
423
+ [ ` Named ` ] ( #named-types ) type, as in ` type Celsius float64 ` .
424
+ (Most ` TypeName ` s for which ` IsAlias() ` is true have a ` Type() ` of
425
+ type ` *types.Alias ` , but ` IsAlias() ` is also true for the predeclared
426
+ ` byte ` and ` rune ` types, which are aliases for ` uint8 ` and ` int32 ` .)
424
427
425
428
426
429
` (*PkgName).Imported ` returns the package (for instance,
@@ -436,9 +439,9 @@ We'll look more closely at this in [Imports](#imports).
436
439
All relationships between the syntax trees (` ast.Node ` s) and type
437
440
checker data structures such as ` Object ` s and ` Type ` s are
438
441
stored in mappings outside the syntax tree itself.
439
- Be aware that the ` go/ast ` package also defines a type called
440
- ` Object ` that resembles---and predates---the type checker's
441
- ` Object ` , and that ` ast.Object ` s are held directly by
442
+ Be aware that the ` go/ast ` package also defines an older deprecated
443
+ type called ` Object ` that resembles---and predates---the type
444
+ checker's ` Object ` , and that ` ast.Object ` s are held directly by
442
445
identifiers in the AST.
443
446
They are created by the parser, which has a necessarily limited view
444
447
of the package, so the information they represent is at best partial and
@@ -974,7 +977,7 @@ Here is the interface:
974
977
}
975
978
976
979
977
- And here are the eleven concrete types that satisfy it:
980
+ And here are the 14 concrete types that satisfy it:
978
981
979
982
980
983
Type = *Basic
@@ -986,12 +989,17 @@ And here are the eleven concrete types that satisfy it:
986
989
| *Struct
987
990
| *Tuple
988
991
| *Signature
992
+ | *Alias
989
993
| *Named
990
994
| *Interface
995
+ | *Union
996
+ | *TypeParam
991
997
992
998
993
999
With the exception of ` Named ` types, instances of ` Type ` are
994
1000
not canonical.
1001
+ (Even for ` Named ` types, parameterized types complicate matters; see
1002
+ https://github.com/golang/exp/tree/master/typeparams/example .)
995
1003
That is, it is usually a mistake to compare types using ` t1==t2 `
996
1004
since this equivalence is not the same as the
997
1005
[ type identity relation] ( https://golang.org/ref/spec#Type_identity )
@@ -1052,8 +1060,8 @@ basic type this is.
1052
1060
The kinds ` Bool ` , ` String ` , ` Int16 ` , and so on,
1053
1061
represent the corresponding predeclared boolean, string, or numeric
1054
1062
types.
1055
- There are two synonyms : ` Byte ` is equivalent to ` Uint8 `
1056
- and ` Rune ` is equivalent to ` Int32 ` .
1063
+ There are two aliases : ` Byte ` is an alias for ` Uint8 `
1064
+ and ` Rune ` is an alias for ` Int32 ` .
1057
1065
The kind ` UnsafePointer ` represents ` unsafe.Pointer ` .
1058
1066
The kinds ` UntypedBool ` , ` UntypedInt ` and so on represent
1059
1067
the six kinds of "untyped" constant types: boolean, integer, rune,
@@ -1082,21 +1090,20 @@ modify it.
1082
1090
1083
1091
1084
1092
A few minor subtleties:
1085
- According to the Go spec, pre-declared types such as ` int ` are
1086
- named types for the purposes of assignability, even though the type
1087
- checker does not represent them using ` Named ` .
1088
- And ` unsafe.Pointer ` is a pointer type for the purpose of
1089
- determining whether the receiver type of a method is legal, even
1090
- though the type checker does not represent it using ` Pointer ` .
1091
-
1092
1093
1094
+ - According to the Go spec, pre-declared types such as ` int ` are
1095
+ named types for the purposes of assignability, even though the type
1096
+ checker does not represent them using ` Named ` .
1093
1097
1094
- The "untyped" types are usually only ascribed to constant expressions,
1095
- but there is one exception.
1096
- A comparison ` x==y ` has type "untyped bool", so the result of
1097
- this expression may be assigned to a variable of type ` bool ` or
1098
- any other named boolean type.
1098
+ - ` unsafe.Pointer ` is a pointer type for the purpose of
1099
+ determining whether the receiver type of a method is legal, even
1100
+ though the type checker does not represent it using ` Pointer ` .
1099
1101
1102
+ - The "untyped" types are usually only ascribed to constant expressions,
1103
+ but there is one exception.
1104
+ A comparison ` x==y ` has type "untyped bool", so the result of
1105
+ this expression may be assigned to a variable of type ` bool ` or
1106
+ any other named boolean type.
1100
1107
1101
1108
1102
1109
## Simple Composite Types
@@ -1262,21 +1269,73 @@ These types are recorded during type checking for later use
1262
1269
1263
1270
1264
1271
1265
- ## Named Types
1272
+ ## Alias Types
1273
+
1274
+ Type declarations come in two forms, aliases and defined types.
1266
1275
1276
+ Aliases, though introduced only in Go 1.9 and not very common, are
1277
+ simplest, so we'll present them first and explain defined types in
1278
+ the next section ("Named Types").
1267
1279
1268
- Type declarations come in two forms.
1269
- The simplest kind, introduced in Go 1.9,
1270
- merely declares a (possibly alternative) name for an existing type.
1271
- Type names used in this way are informally called _ type aliases_ .
1272
- For example, this declaration lets you use the type
1273
- ` Dictionary ` as an alias for ` map[string]string ` :
1280
+ An alias type declaration declares an alternative name for an existing
1281
+ type. For example, this declaration lets you use the type ` Dictionary `
1282
+ as a synonym for ` map[string]string ` :
1274
1283
1275
1284
type Dictionary = map[string]string
1276
1285
1277
- The declaration creates a ` TypeName ` object for ` Dictionary ` . The
1278
- object's ` IsAlias ` method returns true, and its ` Type ` method returns
1279
- a ` Map ` type that represents ` map[string]string ` .
1286
+ The declaration creates a ` TypeName ` object for ` Dictionary ` .
1287
+ The object's ` IsAlias ` method returns true,
1288
+ and its ` Type ` method returns an ` Alias ` :
1289
+
1290
+ type Alias struct{ ... }
1291
+ func (a *Alias) Obj() *TypeName
1292
+ func (a *Alias) Origin() *Alias
1293
+ func (a *Alias) Rhs() Type
1294
+ func (a *Alias) SetTypeParams(tparams []*TypeParam)
1295
+ func (a *Alias) TypeArgs() *TypeList
1296
+ func (a *Alias) TypeParams() *TypeParamList
1297
+
1298
+ The type on the right-hand side of an alias declaration,
1299
+ such as ` map[string]string ` in the example above,
1300
+ can be accessed using the ` Rhs() ` method.
1301
+ The ` types.Unalias(t) ` helper function recursively applies ` Rhs ` ,
1302
+ removing all ` Alias ` types from the operand t and returning the
1303
+ outermost non-alias type.
1304
+
1305
+ The ` Obj ` method returns the declaring ` TypeName ` object, such as
1306
+ ` Dictionary ` ; it provides the name, position, and other properties of
1307
+ the declaration. Conversely, the ` TypeName ` object's ` Type ` method
1308
+ returns the ` Alias ` type.
1309
+
1310
+ Starting with Go 1.24, alias types may have type parameters.
1311
+ For example, this declaration creates an Alias type with
1312
+ a type parameter:
1313
+
1314
+ type Set[T comparable] = map[T]bool
1315
+
1316
+ Each instantiation such as ` Set[string] ` is identical to the
1317
+ corresponding instantiation of the alias' right-hand side type, such
1318
+ as ` map[string]bool ` .
1319
+
1320
+ The remaining methods--Origin, SetTypeParams, TypeArgs,
1321
+ TypeParams--are all concerned with type parameters. For now, see
1322
+ https://github.com/golang/exp/tree/master/typeparams/example .
1323
+
1324
+ Prior to Go 1.22, aliases were not materialized as ` Alias ` types:
1325
+ each reference to an alias type such as ` Dictionary ` would be
1326
+ immediately replaced by its right-hand side type, leaving no
1327
+ indication in the output of the type checker that an alias was
1328
+ present.
1329
+ By materializing alias types, optionally in Go 1.22 and by default
1330
+ starting in Go 1.23, we can more faithfully record the structure of
1331
+ the program, which improves the quality of diagnostic messages and
1332
+ enables certain analyses and code transformations. And, crucially, it
1333
+ enabled the addition of parameterized aliases in Go 1.24.)
1334
+
1335
+
1336
+
1337
+ ## Named Types
1338
+
1280
1339
1281
1340
1282
1341
The second form of type declaration, and the only kind prior to Go
@@ -1292,10 +1351,11 @@ from any other type, including `float64`. The declaration binds the
1292
1351
1293
1352
Since Go 1.9, the Go language specification has used the term _ defined
1294
1353
types_ instead of named types;
1295
- the essential property of a defined type is not that it has a name,
1354
+ the essential property of a defined type is not that it has a name
1355
+ (aliases and type parameters also have names)
1296
1356
but that it is a distinct type with its own method set.
1297
1357
However, the type checker API predates that
1298
- change and instead calls defined types "named" types.
1358
+ change and instead calls defined types ` Named ` types.
1299
1359
1300
1360
type Named struct{ ... }
1301
1361
func (*Named) NumMethods() int
@@ -1321,8 +1381,8 @@ methods than this list. We'll return to this in [Method Sets](#method-sets).
1321
1381
1322
1382
1323
1383
Every ` Type ` has an ` Underlying ` method, but for all of them
1324
- except ` *Named ` , it is simply the identity function.
1325
- For a named type, ` Underlying ` returns its underlying type, which
1384
+ except ` *Named ` and ` *Alias ` , it is simply the identity function.
1385
+ For a named or alias type, ` Underlying ` returns its underlying type, which
1326
1386
is always an unnamed type.
1327
1387
Thus ` Underlying ` returns ` int ` for both ` T ` and
1328
1388
` U ` below.
@@ -1335,14 +1395,13 @@ Thus `Underlying` returns `int` for both `T` and
1335
1395
Clients of the type checker often use type assertions or type switches
1336
1396
with a ` Type ` operand.
1337
1397
When doing so, it is often necessary to switch on the type that
1338
- _ underlies_ the type of interest, and failure to do so may be a
1339
- bug.
1398
+ underlies the type of interest, and failure to do so may be a bug.
1340
1399
1341
1400
This is a common pattern:
1342
1401
1343
1402
1344
1403
// handle types of composite literal
1345
- switch u := t.Underlying().(type) {
1404
+ switch u := t.Underlying().(type) { // remove any *Named and *Alias types
1346
1405
case *Struct: // ...
1347
1406
case *Map: // ...
1348
1407
case *Array, *Slice: // ...
@@ -1423,6 +1482,36 @@ interface `v`, then the type assertion is not legal, as in this example:
1423
1482
1424
1483
1425
1484
1485
+
1486
+ ## TypeParam types
1487
+
1488
+
1489
+ A ` TypeParam ` is the type of a type parameter.
1490
+ For example, the type of the variable ` x ` in the ` identity ` function
1491
+ below is a ` TypeParam ` :
1492
+
1493
+ func identity[T any](x T) T { return x }
1494
+
1495
+ As with ` Alias ` and ` Named ` types, each ` TypeParam ` has an associated
1496
+ ` TypeName ` object that provides its name, position, and other
1497
+ properties of the declaration.
1498
+
1499
+ See https://github.com/golang/exp/tree/master/typeparams/example
1500
+ for a more thorough treatment of parameterized types.
1501
+
1502
+
1503
+
1504
+
1505
+ ## Union types
1506
+
1507
+ A ` Union ` is the type of type-parameter constraint of the form `func
1508
+ f[ T int | string] `.
1509
+
1510
+ See https://github.com/golang/exp/tree/master/typeparams/example
1511
+ for a more thorough treatment of parameterized types.
1512
+
1513
+
1514
+
1426
1515
## TypeAndValue
1427
1516
1428
1517
@@ -2264,10 +2353,9 @@ compiler file formats, and so on.
2264
2353
}
2265
2354
2266
2355
2267
- Most of our examples used the simplest ` Importer ` implementation,
2356
+ Most of our examples used the trivial ` Importer ` implementation,
2268
2357
` importer.Default() ` , provided by the ` go/importer ` package.
2269
- This importer looks in ` $GOROOT ` and ` $GOPATH ` for ` .a `
2270
- files written by the compiler (` gc ` or ` gccgo ` )
2358
+ This importer looks for ` .a ` files written by the compiler
2271
2359
that was used to build the program.
2272
2360
In addition to object code, these files contain _ export data_ ,
2273
2361
that is, a description of all the objects declared by the package, and
@@ -2279,13 +2367,11 @@ transitive dependency.
2279
2367
2280
2368
2281
2369
Compiler export data is compact and efficient to locate, load, and
2282
- parse, but it has several shortcomings.
2283
- First, it does not contain position information for imported
2284
- objects, reducing the quality of certain diagnostic messages.
2285
- Second, it does not contain complete syntax trees nor semantic information
2286
- about the contents of function bodies, so it is not suitable for
2287
- interprocedural analyses.
2288
- Third, compiler object data may be stale. Nothing detects or ensures
2370
+ parse, but it has some shortcomings.
2371
+ First, it does not contain complete syntax trees nor semantic
2372
+ information about the bodies of all functions, so it is not
2373
+ suitable for interprocedural analyses.
2374
+ Second, compiler object data may be stale. Nothing detects or ensures
2289
2375
that the object files are more recent than the source files from which
2290
2376
they were derived.
2291
2377
Generally, object data for standard packages is likely to be
0 commit comments