| // Copyright 2024 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| //go:build go1.22 |
| // +build go1.22 |
| |
| package aliases |
| |
| import ( |
| "go/ast" |
| "go/parser" |
| "go/token" |
| "go/types" |
| "os" |
| "strings" |
| "sync" |
| ) |
| |
| // Alias is an alias of types.Alias. |
| type Alias = types.Alias |
| |
| // Unalias is a wrapper of types.Unalias. |
| func Unalias(t types.Type) types.Type { return types.Unalias(t) } |
| |
| // newAlias is an internal alias around types.NewAlias. |
| // Direct usage is discouraged as the moment. |
| // Try to use NewAlias instead. |
| func newAlias(tname *types.TypeName, rhs types.Type) *Alias { |
| a := types.NewAlias(tname, rhs) |
| // TODO(go.dev/issue/65455): Remove kludgy workaround to set a.actual as a side-effect. |
| Unalias(a) |
| return a |
| } |
| |
| // enabled returns true when types.Aliases are enabled. |
| func enabled() bool { |
| // Use the gotypesalias value in GODEBUG if set. |
| godebug := os.Getenv("GODEBUG") |
| value := -1 // last set value. |
| for _, f := range strings.Split(godebug, ",") { |
| switch f { |
| case "gotypesalias=1": |
| value = 1 |
| case "gotypesalias=0": |
| value = 0 |
| } |
| } |
| switch value { |
| case 0: |
| return false |
| case 1: |
| return true |
| default: |
| return aliasesDefault() |
| } |
| } |
| |
| // aliasesDefault reports if aliases are enabled by default. |
| func aliasesDefault() bool { |
| // Dynamically check if Aliases will be produced from go/types. |
| aliasesDefaultOnce.Do(func() { |
| fset := token.NewFileSet() |
| f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0) |
| pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil) |
| _, gotypesaliasDefault = pkg.Scope().Lookup("A").Type().(*types.Alias) |
| }) |
| return gotypesaliasDefault |
| } |
| |
| var gotypesaliasDefault bool |
| var aliasesDefaultOnce sync.Once |