"cmd/compile/internal/syntax"
"cmd/compile/internal/types2"
"cmd/internal/src"
+ "internal/godebug"
"internal/pkgbits"
)
case pkgbits.ObjAlias:
pos := r.pos()
typ := r.typ()
- return types2.NewTypeName(pos, objPkg, objName, typ)
+ return newAliasTypeName(pos, objPkg, objName, typ)
case pkgbits.ObjConst:
pos := r.pos()
r.Sync(marker)
return r.pkg(), r.String()
}
+
+// newAliasTypeName returns a new TypeName, with a materialized *types2.Alias if supported.
+func newAliasTypeName(pos syntax.Pos, pkg *types2.Package, name string, rhs types2.Type) *types2.TypeName {
+ // Copied from x/tools/internal/aliases.NewAlias via
+ // GOROOT/src/go/internal/gcimporter/ureader.go.
+ if gotypesalias.Value() == "1" {
+ tname := types2.NewTypeName(pos, pkg, name, nil)
+ _ = types2.NewAlias(tname, rhs) // form TypeName -> Alias cycle
+ return tname
+ }
+ return types2.NewTypeName(pos, pkg, name, rhs)
+}
+
+// gotypesalias controls the use of Alias types.
+var gotypesalias = godebug.New("#gotypesalias")
case *types2.TypeName:
if obj.IsAlias() {
w.pos(obj)
- w.typ(types2.Unalias(obj.Type()))
+ t := obj.Type()
+ if alias, ok := t.(*types2.Alias); ok { // materialized alias
+ t = alias.Rhs()
+ }
+ w.typ(t)
return pkgbits.ObjAlias
}
func (a *Alias) Underlying() Type { return unalias(a).Underlying() }
func (a *Alias) String() string { return TypeString(a, nil) }
+// TODO(adonovan): uncomment when proposal #66559 is accepted.
+//
+// // Rhs returns the type R on the right-hand side of an alias
+// // declaration "type A = R", which may be another alias.
+// func (a *Alias) Rhs() Type { return a.fromRHS }
+
// Unalias returns t if it is not an alias type;
// otherwise it follows t's alias chain until it
// reaches a non-alias type which is then returned.
pkg := NewPackage(path, "")
return pkg, NewChecker(conf, pkg, info).Files(files)
}
+
+// Rhs returns the type R on the right-hand side of an alias
+// declaration "type A = R", which may be another alias.
+//
+// TODO(adonovan): move to alias.go (common with go/types) once
+// proposal #66559 is accepted.
+func (a *Alias) Rhs() Type { return a.fromRHS }
import (
"go/token"
"go/types"
+ "internal/godebug"
"internal/pkgbits"
"sort"
)
case pkgbits.ObjAlias:
pos := r.pos()
typ := r.typ()
- declare(types.NewTypeName(pos, objPkg, objName, typ))
+ declare(newAliasTypeName(pos, objPkg, objName, typ))
case pkgbits.ObjConst:
pos := r.pos()
}
return types.Universe
}
+
+// newAliasTypeName returns a new TypeName, with a materialized *types.Alias if supported.
+func newAliasTypeName(pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName {
+ // When GODEBUG=gotypesalias=1, the Type() of the return value is a
+ // *types.Alias. Copied from x/tools/internal/aliases.NewAlias.
+ if godebug.New("gotypesalias").Value() == "1" {
+ tname := types.NewTypeName(pos, pkg, name, nil)
+ _ = types.NewAlias(tname, rhs) // form TypeName -> Alias cycle
+ return tname
+ }
+ return types.NewTypeName(pos, pkg, name, rhs)
+}
func (a *Alias) Underlying() Type { return unalias(a).Underlying() }
func (a *Alias) String() string { return TypeString(a, nil) }
+// TODO(adonovan): uncomment when proposal #66559 is accepted.
+//
+// // Rhs returns the type R on the right-hand side of an alias
+// // declaration "type A = R", which may be another alias.
+// func (a *Alias) Rhs() Type { return a.fromRHS }
+
// Unalias returns t if it is not an alias type;
// otherwise it follows t's alias chain until it
// reaches a non-alias type which is then returned.
"go/parser"
"go/token"
"go/types"
+ "internal/godebug"
"internal/testenv"
"strings"
"testing"
if err != nil {
t.Fatalf("could not parse file %d: %s", i, err)
}
+
+ // Materialized aliases give a different (better)
+ // result for the final test, so skip it for now.
+ // TODO(adonovan): reenable when gotypesalias=1 is the default.
+ if gotypesalias.Value() == "1" && strings.Contains(src, "interface{R}.Read") {
+ continue
+ }
+
files = append(files, file)
}
}
}
+// gotypesalias controls the use of Alias types.
+var gotypesalias = godebug.New("#gotypesalias")
+
// split splits string s at the first occurrence of s, trimming spaces.
func split(s, sep string) (string, string) {
before, after, _ := strings.Cut(s, sep)
return n.Underlying().(*Struct).Field(0).Type().(*Pointer).Elem().(*Named)
}
- Inst := pkg.Scope().Lookup("Inst").Type().(*Pointer).Elem().(*Named)
+ Inst := Unalias(pkg.Scope().Lookup("Inst").Type()).(*Pointer).Elem().(*Named)
Node := firstFieldType(Inst)
Tree := firstFieldType(Node)
if !Identical(Inst, Tree) {
type Eint = E[int]
type Ebool = E[bool]
+type Eint2 = Eint
type S2 struct {
Eint