diff options
| author | Robert Griesemer <gri@google.com> | 2026-01-14 16:10:00 -0800 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-01-22 21:37:55 -0800 |
| commit | 6edb9f9c51f4f9042563f6fcf68701d1fed33c8f (patch) | |
| tree | 8bf472b21d658f6a189a86abb8dbb9790179e648 /src/cmd/compile/internal | |
| parent | 819c53c25f2992113c202644045b93bd3a578f54 (diff) | |
| download | go-6edb9f9c51f4f9042563f6fcf68701d1fed33c8f.tar.xz | |
go/types, types2: remove support for gotypesalias GODEBUG flag
For #76472.
Change-Id: Ia51b41639637b1de916625e73c26f625382be305
Reviewed-on: https://go-review.googlesource.com/c/go/+/736441
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Commit-Queue: Robert Griesemer <gri@google.com>
Diffstat (limited to 'src/cmd/compile/internal')
| -rw-r--r-- | src/cmd/compile/internal/noder/irgen.go | 1 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/alias.go | 18 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/api.go | 10 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/api_test.go | 25 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/check.go | 66 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/check_test.go | 20 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/decl.go | 89 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/issues_test.go | 9 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/object.go | 2 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/object_test.go | 44 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/resolver.go | 13 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/scope.go | 16 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/stdlib_test.go | 7 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/typestring.go | 8 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/typestring_test.go | 4 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/typexpr.go | 13 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/universe.go | 52 |
17 files changed, 77 insertions, 320 deletions
diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 05f0affe8a..387379d2a1 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -56,7 +56,6 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info, map[* IgnoreBranchErrors: true, // parser already checked via syntax.CheckBranches mode Importer: &importer, Sizes: types2.SizesFor("gc", buildcfg.GOARCH), - EnableAlias: true, } if base.Flag.ErrorURL { conf.ErrorURL = " [go.dev/e/%s]" diff --git a/src/cmd/compile/internal/types2/alias.go b/src/cmd/compile/internal/types2/alias.go index d306600ebd..11581bd5a7 100644 --- a/src/cmd/compile/internal/types2/alias.go +++ b/src/cmd/compile/internal/types2/alias.go @@ -21,24 +21,6 @@ import ( // // Like a defined ([Named]) type, an alias type has a name. // Use the [Alias.Obj] method to access its [TypeName] object. -// -// Historically, Alias types were not materialized so that, in the example -// above, A's type was represented by a Basic (int), not an Alias -// whose [Alias.Rhs] is int. But Go 1.24 allows you to declare an -// alias type with type parameters or arguments: -// -// type Set[K comparable] = map[K]bool -// s := make(Set[String]) -// -// and this requires that Alias types be materialized. Use the -// [Alias.TypeParams] and [Alias.TypeArgs] methods to access them. -// -// To ease the transition, the Alias type was introduced in go1.22, -// but the type-checker would not construct values of this type unless -// the GODEBUG=gotypesalias=1 environment variable was provided. -// Starting in go1.23, this variable is enabled by default. -// This setting also causes the predeclared type "any" to be -// represented as an Alias, not a bare [Interface]. type Alias struct { obj *TypeName // corresponding declared alias object orig *Alias // original, uninstantiated alias diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 8752eff992..901984814e 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -175,16 +175,6 @@ type Config struct { // of an error message. ErrorURL must be a format string containing // exactly one "%s" format, e.g. "[go.dev/e/%s]". ErrorURL string - - // If EnableAlias is set, alias declarations produce an Alias type. Otherwise - // the alias information is only in the type name, which points directly to - // the actual (aliased) type. - // - // This setting must not differ among concurrent type-checking operations, - // since it affects the behavior of Universe.Lookup("any"). - // - // This flag will eventually be removed (with Go 1.24 at the earliest). - EnableAlias bool } // Info holds result type information for a type-checked package. diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 4b7012e6c4..a3bb085317 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -2979,7 +2979,6 @@ func TestTooNew(t *testing.T) { // This is a regression test for #66704. func TestUnaliasTooSoonInCycle(t *testing.T) { - t.Setenv("GODEBUG", "gotypesalias=1") const src = `package a var x T[B] // this appears to cause Unalias to be called on B while still Invalid @@ -3005,7 +3004,7 @@ type B = C type C = int ` - pkg := mustTypecheck(src, &Config{EnableAlias: true}, nil) + pkg := mustTypecheck(src, nil, nil) A := pkg.Scope().Lookup("A") got, want := A.Type().(*Alias).Rhs().String(), "p.B" @@ -3014,28 +3013,6 @@ type C = int } } -// Test the hijacking described of "any" described in golang/go#66921, for -// (concurrent) type checking. -func TestAnyHijacking_Check(t *testing.T) { - for _, enableAlias := range []bool{false, true} { - t.Run(fmt.Sprintf("EnableAlias=%t", enableAlias), func(t *testing.T) { - var wg sync.WaitGroup - for i := 0; i < 10; i++ { - wg.Add(1) - go func() { - defer wg.Done() - pkg := mustTypecheck("package p; var x any", &Config{EnableAlias: enableAlias}, nil) - x := pkg.Scope().Lookup("x") - if _, gotAlias := x.Type().(*Alias); gotAlias != enableAlias { - t.Errorf(`Lookup("x").Type() is %T: got Alias: %t, want %t`, x.Type(), gotAlias, enableAlias) - } - }() - } - wg.Wait() - }) - } -} - // This test function only exists for go/types. // func TestVersionIssue69477(t *testing.T) diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 42218b4caf..d714976f74 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -12,7 +12,6 @@ import ( "go/constant" . "internal/types/errors" "os" - "sync/atomic" ) // nopos indicates an unknown position @@ -24,29 +23,6 @@ const debug = false // leave on during development // position tracing for panics during type checking const tracePos = true -// _aliasAny changes the behavior of [Scope.Lookup] for "any" in the -// [Universe] scope. -// -// This is necessary because while Alias creation is controlled by -// [Config.EnableAlias], the representation of "any" is a global. In -// [Scope.Lookup], we select this global representation based on the result of -// [aliasAny], but as a result need to guard against this behavior changing -// during the type checking pass. Therefore we implement the following rule: -// any number of goroutines can type check concurrently with the same -// EnableAlias value, but if any goroutine tries to type check concurrently -// with a different EnableAlias value, we panic. -// -// To achieve this, _aliasAny is a state machine: -// -// 0: no type checking is occurring -// negative: type checking is occurring without EnableAlias set -// positive: type checking is occurring with EnableAlias set -var _aliasAny int32 - -func aliasAny() bool { - return atomic.LoadInt32(&_aliasAny) >= 0 // default true -} - // exprInfo stores information about an untyped expression. type exprInfo struct { isLhs bool // expression is lhs operand of a shift with delayed type-check @@ -200,34 +176,6 @@ func (check *Checker) addDeclDep(to Object) { from.addDep(to) } -// Note: The following three alias-related functions are only used -// when Alias types are not enabled. - -// brokenAlias records that alias doesn't have a determined type yet. -// It also sets alias.typ to Typ[Invalid]. -// Not used if check.conf.EnableAlias is set. -func (check *Checker) brokenAlias(alias *TypeName) { - assert(!check.conf.EnableAlias) - if check.brokenAliases == nil { - check.brokenAliases = make(map[*TypeName]bool) - } - check.brokenAliases[alias] = true - alias.typ = Typ[Invalid] -} - -// validAlias records that alias has the valid type typ (possibly Typ[Invalid]). -func (check *Checker) validAlias(alias *TypeName, typ Type) { - assert(!check.conf.EnableAlias) - delete(check.brokenAliases, alias) - alias.typ = typ -} - -// isBrokenAlias reports whether alias doesn't have a determined type yet. -func (check *Checker) isBrokenAlias(alias *TypeName) bool { - assert(!check.conf.EnableAlias) - return check.brokenAliases[alias] -} - func (check *Checker) rememberUntyped(e syntax.Expr, lhs bool, mode operandMode, typ *Basic, val constant.Value) { m := check.untyped if m == nil { @@ -472,20 +420,6 @@ func (check *Checker) Files(files []*syntax.File) (err error) { // syntax is properly type annotated even in a package containing // errors. func (check *Checker) checkFiles(files []*syntax.File) { - // Ensure that EnableAlias is consistent among concurrent type checking - // operations. See the documentation of [_aliasAny] for details. - if check.conf.EnableAlias { - if atomic.AddInt32(&_aliasAny, 1) <= 0 { - panic("EnableAlias set while !EnableAlias type checking is ongoing") - } - defer atomic.AddInt32(&_aliasAny, -1) - } else { - if atomic.AddInt32(&_aliasAny, -1) >= 0 { - panic("!EnableAlias set while EnableAlias type checking is ongoing") - } - defer atomic.AddInt32(&_aliasAny, 1) - } - print := func(msg string) { if check.conf.Trace { fmt.Println() diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index 8b97a9f676..99bfcc94bf 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -112,8 +112,6 @@ func parseFlags(src []byte, flags *flag.FlagSet) error { // testFiles type-checks the package consisting of the given files, and // compares the resulting errors with the ERROR annotations in the source. -// Except for manual tests, each package is type-checked twice, once without -// use of Alias types, and once with Alias types. // // The srcs slice contains the file content for the files named in the // filenames slice. The colDelta parameter specifies the tolerance for position @@ -122,16 +120,6 @@ func parseFlags(src []byte, flags *flag.FlagSet) error { // // If provided, opts may be used to mutate the Config before type-checking. func testFiles(t *testing.T, filenames []string, srcs [][]byte, colDelta uint, manual bool, opts ...func(*Config)) { - enableAlias := true - opts = append(opts, func(conf *Config) { conf.EnableAlias = enableAlias }) - testFilesImpl(t, filenames, srcs, colDelta, manual, opts...) - if !manual { - enableAlias = false - testFilesImpl(t, filenames, srcs, colDelta, manual, opts...) - } -} - -func testFilesImpl(t *testing.T, filenames []string, srcs [][]byte, colDelta uint, manual bool, opts ...func(*Config)) { if len(filenames) == 0 { t.Fatal("no source files") } @@ -171,12 +159,11 @@ func testFilesImpl(t *testing.T, filenames []string, srcs [][]byte, colDelta uin } // apply flag setting (overrides custom configuration) - var goexperiment, gotypesalias string + var goexperiment string flags := flag.NewFlagSet("", flag.PanicOnError) flags.StringVar(&conf.GoVersion, "lang", "", "") flags.StringVar(&goexperiment, "goexperiment", "", "") flags.BoolVar(&conf.FakeImportC, "fakeImportC", false, "") - flags.StringVar(&gotypesalias, "gotypesalias", "", "") if err := parseFlags(srcs[0], flags); err != nil { t.Fatal(err) } @@ -186,11 +173,6 @@ func testFilesImpl(t *testing.T, filenames []string, srcs [][]byte, colDelta uin defer revert() } - // By default, gotypesalias is not set. - if gotypesalias != "" { - conf.EnableAlias = gotypesalias != "0" - } - // Provide Config.Info with all maps so that info recording is tested. info := Info{ Types: make(map[syntax.Expr]TypeAndValue), diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 25152545ec..be9c63bc8c 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -199,27 +199,7 @@ loop: tparCycle = true break loop } - - // Determine if the type name is an alias or not. For - // package-level objects, use the object map which - // provides syntactic information (which doesn't rely - // on the order in which the objects are set up). For - // local objects, we can rely on the order, so use - // the object's predicate. - // TODO(gri) It would be less fragile to always access - // the syntactic information. We should consider storing - // this information explicitly in the object. - var alias bool - if check.conf.EnableAlias { - alias = obj.IsAlias() - } else { - if d := check.objMap[obj]; d != nil { - alias = d.tdecl.Alias // package-level object - } else { - alias = obj.IsAlias() // function local object - } - } - if !alias { + if !obj.IsAlias() { ndef++ } case *Func: @@ -282,14 +262,8 @@ func (check *Checker) cycleError(cycle []Object, start int) { obj := cycle[start] tname, _ := obj.(*TypeName) if tname != nil { - if check.conf.EnableAlias { - if a, ok := tname.Type().(*Alias); ok { - a.fromRHS = Typ[Invalid] - } - } else { - if tname.IsAlias() { - check.validAlias(tname, Typ[Invalid]) - } + if a, ok := tname.Type().(*Alias); ok { + a.fromRHS = Typ[Invalid] } } @@ -471,45 +445,35 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl) { versionErr = true } - if check.conf.EnableAlias { - alias := check.newAlias(obj, nil) - - // If we could not type the RHS, set it to invalid. This should - // only ever happen if we panic before setting. - defer func() { - if alias.fromRHS == nil { - alias.fromRHS = Typ[Invalid] - unalias(alias) - } - }() + alias := check.newAlias(obj, nil) - // handle type parameters even if not allowed (Alias type is supported) - if tparam0 != nil { - check.openScope(tdecl, "type parameters") - defer check.closeScope() - check.collectTypeParams(&alias.tparams, tdecl.TParamList) + // If we could not type the RHS, set it to invalid. This should + // only ever happen if we panic before setting. + defer func() { + if alias.fromRHS == nil { + alias.fromRHS = Typ[Invalid] + unalias(alias) } + }() - rhs = check.declaredType(tdecl.Type, obj) - assert(rhs != nil) - alias.fromRHS = rhs + // handle type parameters even if not allowed (Alias type is supported) + if tparam0 != nil { + check.openScope(tdecl, "type parameters") + defer check.closeScope() + check.collectTypeParams(&alias.tparams, tdecl.TParamList) + } - // spec: In an alias declaration the given type cannot be a type parameter declared in the same declaration." - // (see also go.dev/issue/75884, go.dev/issue/#75885) - if tpar, ok := rhs.(*TypeParam); ok && alias.tparams != nil && slices.Index(alias.tparams.list(), tpar) >= 0 { - check.error(tdecl.Type, MisplacedTypeParam, "cannot use type parameter declared in alias declaration as RHS") - alias.fromRHS = Typ[Invalid] - } - } else { - if !versionErr && tparam0 != nil { - check.error(tdecl, UnsupportedFeature, "generic type alias requires GODEBUG=gotypesalias=1 or unset") - versionErr = true - } + rhs = check.declaredType(tdecl.Type, obj) + assert(rhs != nil) + alias.fromRHS = rhs - check.brokenAlias(obj) - rhs = check.typ(tdecl.Type) - check.validAlias(obj, rhs) + // spec: In an alias declaration the given type cannot be a type parameter declared in the same declaration." + // (see also go.dev/issue/75884, go.dev/issue/#75885) + if tpar, ok := rhs.(*TypeParam); ok && alias.tparams != nil && slices.Index(alias.tparams.list(), tpar) >= 0 { + check.error(tdecl.Type, MisplacedTypeParam, "cannot use type parameter declared in alias declaration as RHS") + alias.fromRHS = Typ[Invalid] } + return } @@ -520,6 +484,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl) { named := check.newNamed(obj, nil, nil) + // TODO: adjust this comment (gotypesalias) as needed if we don't need allowNilRHS anymore. // The RHS of a named N can be nil if, for example, N is defined as a cycle of aliases with // gotypesalias=0. Consider: // diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go index 8ddb39987a..e564fb38fb 100644 --- a/src/cmd/compile/internal/types2/issues_test.go +++ b/src/cmd/compile/internal/types2/issues_test.go @@ -863,8 +863,7 @@ func TestIssue59944(t *testing.T) { testenv.MustHaveCGO(t) // Methods declared on aliases of cgo types are not permitted. - const src = `// -gotypesalias=1 - + const src = ` package p /* @@ -1011,8 +1010,7 @@ type A = []int type S struct{ A } ` - conf := Config{EnableAlias: true} - pkg := mustTypecheck(src, &conf, nil) + pkg := mustTypecheck(src, nil, nil) S := pkg.Scope().Lookup("S") if S == nil { @@ -1155,8 +1153,7 @@ type ( T A )` - conf := Config{EnableAlias: true} - pkg := mustTypecheck(src, &conf, nil) + pkg := mustTypecheck(src, nil, nil) T := pkg.Scope().Lookup("T").(*TypeName) got := T.String() // this must not panic (was issue) const want = "type p.T struct{}" diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 5d284ee61b..87d8d70a2a 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -591,7 +591,7 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { } if tname.IsAlias() { buf.WriteString(" =") - if alias, ok := typ.(*Alias); ok { // materialized? (gotypesalias=1) + if alias, ok := typ.(*Alias); ok { // materialized? TODO(gri) Do we still need this (e.g. for byte, rune)? typ = alias.fromRHS } } else if t, _ := typ.(*TypeParam); t != nil { diff --git a/src/cmd/compile/internal/types2/object_test.go b/src/cmd/compile/internal/types2/object_test.go index 4f1a653ff3..58dfc547dc 100644 --- a/src/cmd/compile/internal/types2/object_test.go +++ b/src/cmd/compile/internal/types2/object_test.go @@ -80,32 +80,31 @@ func TestEmbeddedMethod(t *testing.T) { } var testObjects = []struct { - src string - obj string - want string - alias bool // needs materialized (and possibly generic) aliases + src string + obj string + want string }{ - {"import \"io\"; var r io.Reader", "r", "var p.r io.Reader", false}, + {"import \"io\"; var r io.Reader", "r", "var p.r io.Reader"}, - {"const c = 1.2", "c", "const p.c untyped float", false}, - {"const c float64 = 3.14", "c", "const p.c float64", false}, + {"const c = 1.2", "c", "const p.c untyped float"}, + {"const c float64 = 3.14", "c", "const p.c float64"}, - {"type t struct{f int}", "t", "type p.t struct{f int}", false}, - {"type t func(int)", "t", "type p.t func(int)", false}, - {"type t[P any] struct{f P}", "t", "type p.t[P any] struct{f P}", false}, - {"type t[P any] struct{f P}", "t.P", "type parameter P any", false}, - {"type C interface{m()}; type t[P C] struct{}", "t.P", "type parameter P p.C", false}, + {"type t struct{f int}", "t", "type p.t struct{f int}"}, + {"type t func(int)", "t", "type p.t func(int)"}, + {"type t[P any] struct{f P}", "t", "type p.t[P any] struct{f P}"}, + {"type t[P any] struct{f P}", "t.P", "type parameter P any"}, + {"type C interface{m()}; type t[P C] struct{}", "t.P", "type parameter P p.C"}, - {"type t = struct{f int}", "t", "type p.t = struct{f int}", false}, - {"type t = func(int)", "t", "type p.t = func(int)", false}, - {"type A = B; type B = int", "A", "type p.A = p.B", true}, - {"type A[P ~int] = struct{}", "A", "type p.A[P ~int] = struct{}", true}, - {"var v int", "v", "var p.v int", false}, + {"type t = struct{f int}", "t", "type p.t = struct{f int}"}, + {"type t = func(int)", "t", "type p.t = func(int)"}, + {"type A = B; type B = int", "A", "type p.A = p.B"}, + {"type A[P ~int] = struct{}", "A", "type p.A[P ~int] = struct{}"}, + {"var v int", "v", "var p.v int"}, - {"func f(int) string", "f", "func p.f(int) string", false}, - {"func g[P any](x P){}", "g", "func p.g[P any](x P)", false}, - {"func g[P interface{~int}](x P){}", "g.P", "type parameter P interface{~int}", false}, - {"", "any", "type any = interface{}", false}, + {"func f(int) string", "f", "func p.f(int) string"}, + {"func g[P any](x P){}", "g", "func p.g[P any](x P)"}, + {"func g[P interface{~int}](x P){}", "g.P", "type parameter P interface{~int}"}, + {"", "any", "type any = interface{}"}, } func TestObjectString(t *testing.T) { @@ -114,8 +113,7 @@ func TestObjectString(t *testing.T) { for i, test := range testObjects { t.Run(fmt.Sprint(i), func(t *testing.T) { src := "package p; " + test.src - conf := Config{Error: func(error) {}, Importer: defaultImporter(), EnableAlias: test.alias} - pkg, err := typecheck(src, &conf, nil) + pkg, err := typecheck(src, nil, nil) if err != nil { t.Fatalf("%s: %s", src, err) } diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go index 2418de5268..f075f5447f 100644 --- a/src/cmd/compile/internal/types2/resolver.go +++ b/src/cmd/compile/internal/types2/resolver.go @@ -646,13 +646,12 @@ func (check *Checker) packageObjects() { } } - if false && check.conf.EnableAlias { - // With Alias nodes we can process declarations in any order. + if false { + // TODO: determine if we can enable this code now or + // if there are still problems with cycles and + // aliases. // - // TODO(adonovan): unfortunately, Alias nodes - // (GODEBUG=gotypesalias=1) don't entirely resolve - // problems with cycles. For example, in - // GOROOT/test/typeparam/issue50259.go, + // For example, in GOROOT/test/typeparam/issue50259.go, // // type T[_ any] struct{} // type A T[B] @@ -667,7 +666,7 @@ func (check *Checker) packageObjects() { check.objDecl(obj) } } else { - // Without Alias nodes, we process non-alias type declarations first, followed by + // To avoid problems with cycles, process non-alias type declarations first, followed by // alias declarations, and then everything else. This appears to avoid most situations // where the type of an alias is needed before it is available. // There may still be cases where this is not good enough (see also go.dev/issue/25838). diff --git a/src/cmd/compile/internal/types2/scope.go b/src/cmd/compile/internal/types2/scope.go index 10c624be2e..90f52a7737 100644 --- a/src/cmd/compile/internal/types2/scope.go +++ b/src/cmd/compile/internal/types2/scope.go @@ -67,21 +67,7 @@ func (s *Scope) Child(i int) *Scope { return s.children[i] } // Lookup returns the object in scope s with the given name if such an // object exists; otherwise the result is nil. -func (s *Scope) Lookup(name string) Object { - obj := resolve(name, s.elems[name]) - // Hijack Lookup for "any": with gotypesalias=1, we want the Universe to - // return an Alias for "any", and with gotypesalias=0 we want to return - // the legacy representation of aliases. - // - // This is rather tricky, but works out after auditing of the usage of - // s.elems. The only external API to access scope elements is Lookup. - // - // TODO: remove this once gotypesalias=0 is no longer supported. - if obj == universeAnyAlias && !aliasAny() { - return universeAnyNoAlias - } - return obj -} +func (s *Scope) Lookup(name string) Object { return resolve(name, s.elems[name]) } // lookupIgnoringCase returns the objects in scope s whose names match // the given name ignoring case. If exported is set, only exported names diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index ee49bbddfa..a85e66a363 100644 --- a/src/cmd/compile/internal/types2/stdlib_test.go +++ b/src/cmd/compile/internal/types2/stdlib_test.go @@ -332,10 +332,6 @@ func TestStdFixed(t *testing.T) { "issue49814.go", // go/types does not have constraints on array size "issue56103.go", // anonymous interface cycles; will be a type checker error in 1.22 "issue52697.go", // types2 does not have constraints on stack size - "issue68054.go", // this test requires GODEBUG=gotypesalias=1 - "issue68580.go", // this test requires GODEBUG=gotypesalias=1 - "issue73309.go", // this test requires GODEBUG=gotypesalias=1 - "issue73309b.go", // this test requires GODEBUG=gotypesalias=1 // These tests requires runtime/cgo.Incomplete, which is only available on some platforms. // However, types2 does not know about build constraints. @@ -402,8 +398,7 @@ func typecheckFiles(path string, filenames []string, importer Importer) (*Packag Error: func(err error) { errs = append(errs, err) }, - Importer: importer, - EnableAlias: true, + Importer: importer, } info := Info{Uses: make(map[*syntax.Name]Object)} pkg, _ := conf.Check(path, files, &info) diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index e68f6a2886..e635b38527 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -211,14 +211,6 @@ func (w *typeWriter) typ(typ Type) { case *Interface: if w.ctxt == nil { - if t == universeAnyAlias.Type().Underlying() { - // When not hashing, we can try to improve type strings by writing "any" - // for a type that is pointer-identical to universeAny. - // TODO(rfindley): this logic should not be necessary with - // gotypesalias=1. Remove once that is always the case. - w.string("any") - break - } if t == asNamed(universeComparable.Type()).underlying { w.string("interface{comparable}") break diff --git a/src/cmd/compile/internal/types2/typestring_test.go b/src/cmd/compile/internal/types2/typestring_test.go index c2be40da29..fe787771e3 100644 --- a/src/cmd/compile/internal/types2/typestring_test.go +++ b/src/cmd/compile/internal/types2/typestring_test.go @@ -82,10 +82,10 @@ var independentTestTypes = []testEntry{ dup(`interface{String() string; m(int) float32}`), dup("interface{int | float32 | complex128}"), dup("interface{int | ~float32 | ~complex128}"), - dup("any"), dup("interface{comparable}"), - {"comparable", "interface{comparable}"}, {"error", "interface{Error() string}"}, + {"any", "interface{}"}, + {"comparable", "interface{comparable}"}, // maps dup("map[string]int"), diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 7d5932eec1..ac81b838de 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -30,14 +30,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, wantType bool) { check.errorf(e, UndeclaredName, "undefined: %s", e.Value) } return - case universeComparable: - if !check.verifyVersionf(e, go1_18, "predeclared %s", e.Value) { - return // avoid follow-on errors - } - } - // Because the representation of any depends on gotypesalias, we don't check - // pointer identity here. - if obj.Name() == "any" && obj.Parent() == Universe { + case universeAny, universeComparable: if !check.verifyVersionf(e, go1_18, "predeclared %s", e.Value) { return // avoid follow-on errors } @@ -109,10 +102,6 @@ func (check *Checker) ident(x *operand, e *syntax.Name, wantType bool) { x.mode = constant_ case *TypeName: - if !check.conf.EnableAlias && check.isBrokenAlias(obj) { - check.errorf(e, InvalidDeclCycle, "invalid use of type alias %s in recursive type (see go.dev/issue/50729)", obj.name) - return - } x.mode = typexpr case *Var: diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index 1ecef97d51..6a649843d1 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -24,9 +24,8 @@ var ( universeBool Type universeByte Type // uint8 alias, but has name "byte" universeRune Type // int32 alias, but has name "rune" - universeAnyNoAlias *TypeName - universeAnyAlias *TypeName universeError Type + universeAny Object universeComparable Object ) @@ -76,44 +75,15 @@ func defPredeclaredTypes() { for _, t := range Typ { def(NewTypeName(nopos, nil, t.name, t)) } + for _, t := range basicAliases { def(NewTypeName(nopos, nil, t.name, t)) } - // type any = interface{} - // - // Implement two representations of any: one for the legacy gotypesalias=0, - // and one for gotypesalias=1. This is necessary for consistent - // representation of interface aliases during type checking, and is - // implemented via hijacking [Scope.Lookup] for the [Universe] scope. - // - // Both representations use the same distinguished pointer for their RHS - // interface type, allowing us to detect any (even with the legacy - // representation), and format it as "any" rather than interface{}, which - // clarifies user-facing error messages significantly. - // - // TODO(rfindley): once the gotypesalias GODEBUG variable is obsolete (and we - // consistently use the Alias node), we should be able to clarify user facing - // error messages without using a distinguished pointer for the any - // interface. - { - universeAnyNoAlias = NewTypeName(nopos, nil, "any", &Interface{complete: true, tset: &topTypeSet}) - // ensure that the any TypeName reports a consistent Parent, after - // hijacking Universe.Lookup with gotypesalias=0. - universeAnyNoAlias.setParent(Universe) - - // It shouldn't matter which representation of any is actually inserted - // into the Universe, but we lean toward the future and insert the Alias - // representation. - universeAnyAlias = NewTypeName(nopos, nil, "any", nil) - _ = NewAlias(universeAnyAlias, universeAnyNoAlias.Type().Underlying()) // Link TypeName and Alias - def(universeAnyAlias) - } - // type error interface{ Error() string } { obj := NewTypeName(nopos, nil, "error", nil) - typ := (*Checker)(nil).newNamed(obj, nil, nil) + typ := NewNamed(obj, nil, nil) // error.Error() string recv := newVar(RecvVar, nopos, nil, "", typ) @@ -130,16 +100,17 @@ func defPredeclaredTypes() { def(obj) } + // type any = interface{} + { + obj := NewTypeName(nopos, nil, "any", nil) + NewAlias(obj, &emptyInterface) + def(obj) + } + // type comparable interface{} // marked as comparable { obj := NewTypeName(nopos, nil, "comparable", nil) - typ := (*Checker)(nil).newNamed(obj, nil, nil) - - // interface{} // marked as comparable - ityp := &Interface{complete: true, tset: &_TypeSet{nil, allTermlist, true}} - - typ.fromRHS = ityp - typ.Underlying() + NewNamed(obj, &Interface{complete: true, tset: &_TypeSet{nil, allTermlist, true}}, nil) def(obj) } } @@ -278,6 +249,7 @@ func init() { universeByte = Universe.Lookup("byte").Type() universeRune = Universe.Lookup("rune").Type() universeError = Universe.Lookup("error").Type() + universeAny = Universe.Lookup("any") universeComparable = Universe.Lookup("comparable") } |
