Skip to content

Commit 30de0b5

Browse files
griesemergopherbot
authored andcommitted
go/types, types2: implement Alias proposal (export API)
This CL exports the previously unexported Alias type and corresponding functions and methods per issue #63223. Whether Alias types are used or not is controlled by the gotypesalias setting with the GODEBUG environment variable. Setting gotypesalias to "1" enables the Alias types: GODEBUG=gotypesalias=1 By default, gotypesalias is not set. Adjust test cases that enable/disable the use of Alias types to use -gotypesalias=1 or -gotypesalias=0 rather than -alias and -alias=false for consistency and to avoid confusion. For #63223. Change-Id: I51308cad3320981afac97dd8c6f6a416fdb0be55 Reviewed-on: https://go-review.googlesource.com/c/go/+/541737 Run-TryBot: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Robert Griesemer <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent 42bd21b commit 30de0b5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+209
-159
lines changed

api/next/63223.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pkg go/types, func NewAlias(*TypeName, Type) *Alias #63223
2+
pkg go/types, func Unalias(Type) Type #63223
3+
pkg go/types, method (*Alias) Obj() *TypeName #63223
4+
pkg go/types, method (*Alias) String() string #63223
5+
pkg go/types, method (*Alias) Underlying() Type #63223
6+
pkg go/types, type Alias struct #63223

doc/godebug.md

+7
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ patterns and unescape both patterns and request paths by segment.
143143
This behavior can be controlled by the
144144
[`httpmuxgo121` setting](/pkg/net/http/#ServeMux).
145145

146+
Go 1.22 added the [Alias type](/pkg/go/types#Alias) to [go/types](/pkg/go/types)
147+
for the explicit representation of [type aliases](/ref/spec#Type_declarations).
148+
Whether the type checker produces `Alias` types or not is controlled by the
149+
[`gotypesalias` setting](/pkg/go/types#Alias).
150+
For Go 1.22 it defaults to `gotypesalias=0`.
151+
For Go 1.23, `gotypealias=1` will become the default.
152+
This setting will be removed in a future release, Go 1.24 at the earliest.
146153

147154
### Go 1.21
148155

src/cmd/compile/internal/types2/alias.go

+21-18
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,42 @@ package types2
66

77
import "fmt"
88

9-
// Names starting with a _ are intended to be exported eventually
10-
// (go.dev/issue/63223).
11-
12-
// An _Alias represents an alias type.
13-
type _Alias struct {
9+
// An Alias represents an alias type.
10+
// Whether or not Alias types are created is controlled by the
11+
// gotypesalias setting with the GODEBUG environment variable.
12+
// For gotypesalias=1, alias declarations produce an Alias type.
13+
// Otherwise, the alias information is only in the type name,
14+
// which points directly to the actual (aliased) type.
15+
type Alias struct {
1416
obj *TypeName // corresponding declared alias object
1517
fromRHS Type // RHS of type alias declaration; may be an alias
1618
actual Type // actual (aliased) type; never an alias
1719
}
1820

19-
// _NewAlias creates a new Alias type with the given type name and rhs.
21+
// NewAlias creates a new Alias type with the given type name and rhs.
2022
// rhs must not be nil.
21-
func _NewAlias(obj *TypeName, rhs Type) *_Alias {
23+
func NewAlias(obj *TypeName, rhs Type) *Alias {
2224
return (*Checker)(nil).newAlias(obj, rhs)
2325
}
2426

25-
func (a *_Alias) Underlying() Type { return a.actual.Underlying() }
26-
func (a *_Alias) String() string { return TypeString(a, nil) }
27+
func (a *Alias) Obj() *TypeName { return a.obj }
28+
func (a *Alias) Underlying() Type { return a.actual.Underlying() }
29+
func (a *Alias) String() string { return TypeString(a, nil) }
2730

2831
// Type accessors
2932

30-
// _Unalias returns t if it is not an alias type;
33+
// Unalias returns t if it is not an alias type;
3134
// otherwise it follows t's alias chain until it
3235
// reaches a non-alias type which is then returned.
3336
// Consequently, the result is never an alias type.
34-
func _Unalias(t Type) Type {
35-
if a0, _ := t.(*_Alias); a0 != nil {
37+
func Unalias(t Type) Type {
38+
if a0, _ := t.(*Alias); a0 != nil {
3639
if a0.actual != nil {
3740
return a0.actual
3841
}
3942
for a := a0; ; {
4043
t = a.fromRHS
41-
a, _ = t.(*_Alias)
44+
a, _ = t.(*Alias)
4245
if a == nil {
4346
break
4447
}
@@ -54,15 +57,15 @@ func _Unalias(t Type) Type {
5457
// asNamed returns t as *Named if that is t's
5558
// actual type. It returns nil otherwise.
5659
func asNamed(t Type) *Named {
57-
n, _ := _Unalias(t).(*Named)
60+
n, _ := Unalias(t).(*Named)
5861
return n
5962
}
6063

6164
// newAlias creates a new Alias type with the given type name and rhs.
6265
// rhs must not be nil.
63-
func (check *Checker) newAlias(obj *TypeName, rhs Type) *_Alias {
66+
func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias {
6467
assert(rhs != nil)
65-
a := &_Alias{obj, rhs, nil}
68+
a := &Alias{obj, rhs, nil}
6669
if obj.typ == nil {
6770
obj.typ = a
6871
}
@@ -75,6 +78,6 @@ func (check *Checker) newAlias(obj *TypeName, rhs Type) *_Alias {
7578
return a
7679
}
7780

78-
func (a *_Alias) cleanup() {
79-
_Unalias(a)
81+
func (a *Alias) cleanup() {
82+
Unalias(a)
8083
}

src/cmd/compile/internal/types2/api.go

-5
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,6 @@ type Config struct {
170170
// for unused imports.
171171
DisableUnusedImportCheck bool
172172

173-
// If EnableAlias is set, alias declarations produce an _Alias type.
174-
// Otherwise the alias information is only in the type name, which
175-
// points directly to the actual (aliased) type.
176-
_EnableAlias bool
177-
178173
// If a non-empty ErrorURL format string is provided, it is used
179174
// to format an error URL link that is appended to the first line
180175
// of an error message. ErrorURL must be a format string containing

src/cmd/compile/internal/types2/check.go

+22-11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"errors"
1212
"fmt"
1313
"go/constant"
14+
"internal/godebug"
1415
"internal/goversion"
1516
. "internal/types/errors"
1617
)
@@ -21,6 +22,9 @@ var nopos syntax.Pos
2122
// debugging/development support
2223
const debug = false // leave on during development
2324

25+
// gotypesalias controls the use of Alias types.
26+
var gotypesalias = godebug.New("gotypesalias")
27+
2428
// exprInfo stores information about an untyped expression.
2529
type exprInfo struct {
2630
isLhs bool // expression is lhs operand of a shift with delayed type-check
@@ -93,6 +97,12 @@ type actionDesc struct {
9397
type Checker struct {
9498
// package information
9599
// (initialized by NewChecker, valid for the life-time of checker)
100+
101+
// If enableAlias is set, alias declarations produce an Alias type.
102+
// Otherwise the alias information is only in the type name, which
103+
// points directly to the actual (aliased) type.
104+
enableAlias bool
105+
96106
conf *Config
97107
ctxt *Context // context for de-duplicating instances
98108
pkg *Package
@@ -153,13 +163,13 @@ func (check *Checker) addDeclDep(to Object) {
153163
}
154164

155165
// Note: The following three alias-related functions are only used
156-
// when _Alias types are not enabled.
166+
// when Alias types are not enabled.
157167

158168
// brokenAlias records that alias doesn't have a determined type yet.
159169
// It also sets alias.typ to Typ[Invalid].
160-
// Not used if check.conf._EnableAlias is set.
170+
// Not used if check.enableAlias is set.
161171
func (check *Checker) brokenAlias(alias *TypeName) {
162-
assert(!check.conf._EnableAlias)
172+
assert(!check.enableAlias)
163173
if check.brokenAliases == nil {
164174
check.brokenAliases = make(map[*TypeName]bool)
165175
}
@@ -169,14 +179,14 @@ func (check *Checker) brokenAlias(alias *TypeName) {
169179

170180
// validAlias records that alias has the valid type typ (possibly Typ[Invalid]).
171181
func (check *Checker) validAlias(alias *TypeName, typ Type) {
172-
assert(!check.conf._EnableAlias)
182+
assert(!check.enableAlias)
173183
delete(check.brokenAliases, alias)
174184
alias.typ = typ
175185
}
176186

177187
// isBrokenAlias reports whether alias doesn't have a determined type yet.
178188
func (check *Checker) isBrokenAlias(alias *TypeName) bool {
179-
assert(!check.conf._EnableAlias)
189+
assert(!check.enableAlias)
180190
return check.brokenAliases[alias]
181191
}
182192

@@ -246,12 +256,13 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
246256
// (previously, pkg.goVersion was mutated here: go.dev/issue/61212)
247257

248258
return &Checker{
249-
conf: conf,
250-
ctxt: conf.Context,
251-
pkg: pkg,
252-
Info: info,
253-
objMap: make(map[Object]*declInfo),
254-
impMap: make(map[importKey]*Package),
259+
enableAlias: gotypesalias.Value() == "1",
260+
conf: conf,
261+
ctxt: conf.Context,
262+
pkg: pkg,
263+
Info: info,
264+
objMap: make(map[Object]*declInfo),
265+
impMap: make(map[importKey]*Package),
255266
}
256267
}
257268

src/cmd/compile/internal/types2/check_test.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func parseFlags(src []byte, flags *flag.FlagSet) error {
113113
// testFiles type-checks the package consisting of the given files, and
114114
// compares the resulting errors with the ERROR annotations in the source.
115115
// Except for manual tests, each package is type-checked twice, once without
116-
// use of _Alias types, and once with _Alias types.
116+
// use of Alias types, and once with Alias types.
117117
//
118118
// The srcs slice contains the file content for the files named in the
119119
// filenames slice. The colDelta parameter specifies the tolerance for position
@@ -122,9 +122,11 @@ func parseFlags(src []byte, flags *flag.FlagSet) error {
122122
//
123123
// If provided, opts may be used to mutate the Config before type-checking.
124124
func testFiles(t *testing.T, filenames []string, srcs [][]byte, colDelta uint, manual bool, opts ...func(*Config)) {
125+
// Alias types are disabled by default
125126
testFilesImpl(t, filenames, srcs, colDelta, manual, opts...)
126127
if !manual {
127-
testFilesImpl(t, filenames, srcs, colDelta, manual, append(opts, func(conf *Config) { *boolFieldAddr(conf, "_EnableAlias") = true })...)
128+
t.Setenv("GODEBUG", "gotypesalias=1")
129+
testFilesImpl(t, filenames, srcs, colDelta, manual, opts...)
128130
}
129131
}
130132

@@ -168,15 +170,16 @@ func testFilesImpl(t *testing.T, filenames []string, srcs [][]byte, colDelta uin
168170
}
169171

170172
// apply flag setting (overrides custom configuration)
171-
var goexperiment string
173+
var goexperiment, gotypesalias string
172174
flags := flag.NewFlagSet("", flag.PanicOnError)
173175
flags.StringVar(&conf.GoVersion, "lang", "", "")
174176
flags.StringVar(&goexperiment, "goexperiment", "", "")
175177
flags.BoolVar(&conf.FakeImportC, "fakeImportC", false, "")
176-
flags.BoolVar(boolFieldAddr(&conf, "_EnableAlias"), "alias", false, "")
178+
flags.StringVar(&gotypesalias, "gotypesalias", "", "")
177179
if err := parseFlags(srcs[0], flags); err != nil {
178180
t.Fatal(err)
179181
}
182+
180183
exp, err := buildcfg.ParseGOEXPERIMENT(runtime.GOOS, runtime.GOARCH, goexperiment)
181184
if err != nil {
182185
t.Fatal(err)
@@ -187,6 +190,11 @@ func testFilesImpl(t *testing.T, filenames []string, srcs [][]byte, colDelta uin
187190
}()
188191
buildcfg.Experiment = *exp
189192

193+
// By default, gotypesalias is not set.
194+
if gotypesalias != "" {
195+
t.Setenv("GODEBUG", "gotypesalias="+gotypesalias)
196+
}
197+
190198
// Provide Config.Info with all maps so that info recording is tested.
191199
info := Info{
192200
Types: make(map[syntax.Expr]TypeAndValue),

src/cmd/compile/internal/types2/decl.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ loop:
251251
// the syntactic information. We should consider storing
252252
// this information explicitly in the object.
253253
var alias bool
254-
if check.conf._EnableAlias {
254+
if check.enableAlias {
255255
alias = obj.IsAlias()
256256
} else {
257257
if d := check.objMap[obj]; d != nil {
@@ -328,7 +328,7 @@ func (check *Checker) cycleError(cycle []Object) {
328328
if tname != nil && tname.IsAlias() {
329329
// If we use Alias nodes, it is initialized with Typ[Invalid].
330330
// TODO(gri) Adjust this code if we initialize with nil.
331-
if !check.conf._EnableAlias {
331+
if !check.enableAlias {
332332
check.validAlias(tname, Typ[Invalid])
333333
}
334334
}
@@ -514,7 +514,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *TypeN
514514
// alias declaration
515515
if aliasDecl {
516516
check.verifyVersionf(tdecl, go1_9, "type aliases")
517-
if check.conf._EnableAlias {
517+
if check.enableAlias {
518518
// TODO(gri) Should be able to use nil instead of Typ[Invalid] to mark
519519
// the alias as incomplete. Currently this causes problems
520520
// with certain cycles. Investigate.
@@ -523,7 +523,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *TypeN
523523
rhs = check.definedType(tdecl.Type, obj)
524524
assert(rhs != nil)
525525
alias.fromRHS = rhs
526-
_Unalias(alias) // resolve alias.actual
526+
Unalias(alias) // resolve alias.actual
527527
} else {
528528
check.brokenAlias(obj)
529529
rhs = check.typ(tdecl.Type)

src/cmd/compile/internal/types2/infer.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,8 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) {
542542
case *Basic:
543543
// nothing to do
544544

545-
case *_Alias:
546-
return w.isParameterized(_Unalias(t))
545+
case *Alias:
546+
return w.isParameterized(Unalias(t))
547547

548548
case *Array:
549549
return w.isParameterized(t.elem)
@@ -696,8 +696,8 @@ func (w *cycleFinder) typ(typ Type) {
696696
case *Basic:
697697
// nothing to do
698698

699-
case *_Alias:
700-
w.typ(_Unalias(t))
699+
case *Alias:
700+
w.typ(Unalias(t))
701701

702702
case *Array:
703703
w.typ(t.elem)

src/cmd/compile/internal/types2/issues_test.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -989,9 +989,8 @@ type A = []int
989989
type S struct{ A }
990990
`
991991

992-
var conf Config
993-
*boolFieldAddr(&conf, "_EnableAlias") = true
994-
pkg := mustTypecheck(src, &conf, nil)
992+
t.Setenv("GODEBUG", "gotypesalias=1")
993+
pkg := mustTypecheck(src, nil, nil)
995994

996995
S := pkg.Scope().Lookup("S")
997996
if S == nil {

src/cmd/compile/internal/types2/lookup.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ func (check *Checker) newAssertableTo(pos syntax.Pos, V, T Type, cause *string)
527527
// with an underlying pointer type!) and returns its base and true.
528528
// Otherwise it returns (typ, false).
529529
func deref(typ Type) (Type, bool) {
530-
if p, _ := _Unalias(typ).(*Pointer); p != nil {
530+
if p, _ := Unalias(typ).(*Pointer); p != nil {
531531
// p.base should never be nil, but be conservative
532532
if p.base == nil {
533533
if debug {

src/cmd/compile/internal/types2/mono.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func (w *monoGraph) assign(pkg *Package, pos syntax.Pos, tpar *TypeParam, targ T
208208
// type parameters.
209209
var do func(typ Type)
210210
do = func(typ Type) {
211-
switch typ := _Unalias(typ).(type) {
211+
switch typ := Unalias(typ).(type) {
212212
default:
213213
panic("unexpected type")
214214

src/cmd/compile/internal/types2/named.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,8 @@ func (t *Named) AddMethod(m *Func) {
453453
}
454454
}
455455

456-
// TODO(gri) Investigate if _Unalias can be moved to where underlying is set.
457-
func (t *Named) Underlying() Type { return _Unalias(t.resolve().underlying) }
456+
// TODO(gri) Investigate if Unalias can be moved to where underlying is set.
457+
func (t *Named) Underlying() Type { return Unalias(t.resolve().underlying) }
458458
func (t *Named) String() string { return TypeString(t, nil) }
459459

460460
// ----------------------------------------------------------------------------

src/cmd/compile/internal/types2/object.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ func (obj *TypeName) IsAlias() bool {
285285
switch t := obj.typ.(type) {
286286
case nil:
287287
return false
288-
// case *_Alias:
288+
// case *Alias:
289289
// handled by default case
290290
case *Basic:
291291
// unsafe.Pointer is not an alias.

0 commit comments

Comments
 (0)