}
if tname.IsAlias() {
buf.WriteString(" =")
+ if alias, ok := typ.(*Alias); ok { // materialized? (gotypesalias=1)
+ typ = alias.fromRHS
+ }
} else if t, _ := typ.(*TypeParam); t != nil {
typ = t.bound
} else {
// TODO(gri) should this be fromRHS for *Named?
+ // (See discussion in #66559.)
typ = under(typ)
}
}
package types2_test
import (
+ "fmt"
"internal/testenv"
"strings"
"testing"
}
var testObjects = []struct {
- src string
- obj string
- want string
+ src string
+ obj string
+ want string
+ alias bool // needs materialized aliases
}{
- {"import \"io\"; var r io.Reader", "r", "var p.r io.Reader"},
+ {"import \"io\"; var r io.Reader", "r", "var p.r io.Reader", false},
- {"const c = 1.2", "c", "const p.c untyped float"},
- {"const c float64 = 3.14", "c", "const p.c float64"},
+ {"const c = 1.2", "c", "const p.c untyped float", false},
+ {"const c float64 = 3.14", "c", "const p.c float64", 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 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 = 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},
- {"var v int", "v", "var p.v int"},
+ {"var v int", "v", "var p.v int", 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 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 TestObjectString(t *testing.T) {
testenv.MustHaveGoBuild(t)
- for _, test := range testObjects {
- src := "package p; " + test.src
- pkg, err := typecheck(src, nil, nil)
- if err != nil {
- t.Errorf("%s: %s", src, err)
- continue
- }
+ for i, test := range testObjects {
+ t.Run(fmt.Sprint(i), func(t *testing.T) {
+ if test.alias {
+ t.Setenv("GODEBUG", "gotypesalias=1")
+ }
- names := strings.Split(test.obj, ".")
- if len(names) != 1 && len(names) != 2 {
- t.Errorf("%s: invalid object path %s", test.src, test.obj)
- continue
- }
- _, obj := pkg.Scope().LookupParent(names[0], nopos)
- if obj == nil {
- t.Errorf("%s: %s not found", test.src, names[0])
- continue
- }
- if len(names) == 2 {
- if typ, ok := obj.Type().(interface{ TypeParams() *TypeParamList }); ok {
- obj = lookupTypeParamObj(typ.TypeParams(), names[1])
- if obj == nil {
- t.Errorf("%s: %s not found", test.src, test.obj)
- continue
+ src := "package p; " + test.src
+ pkg, err := typecheck(src, nil, nil)
+ if err != nil {
+ t.Fatalf("%s: %s", src, err)
+ }
+
+ names := strings.Split(test.obj, ".")
+ if len(names) != 1 && len(names) != 2 {
+ t.Fatalf("%s: invalid object path %s", test.src, test.obj)
+ }
+ _, obj := pkg.Scope().LookupParent(names[0], nopos)
+ if obj == nil {
+ t.Fatalf("%s: %s not found", test.src, names[0])
+ }
+ if len(names) == 2 {
+ if typ, ok := obj.Type().(interface{ TypeParams() *TypeParamList }); ok {
+ obj = lookupTypeParamObj(typ.TypeParams(), names[1])
+ if obj == nil {
+ t.Fatalf("%s: %s not found", test.src, test.obj)
+ }
+ } else {
+ t.Fatalf("%s: %s has no type parameters", test.src, names[0])
}
- } else {
- t.Errorf("%s: %s has no type parameters", test.src, names[0])
- continue
}
- }
- if got := obj.String(); got != test.want {
- t.Errorf("%s: got %s, want %s", test.src, got, test.want)
- }
+ if got := obj.String(); got != test.want {
+ t.Errorf("%s: got %s, want %s", test.src, got, test.want)
+ }
+ })
}
}
}
if tname.IsAlias() {
buf.WriteString(" =")
+ if alias, ok := typ.(*Alias); ok { // materialized? (gotypesalias=1)
+ typ = alias.fromRHS
+ }
} else if t, _ := typ.(*TypeParam); t != nil {
typ = t.bound
} else {
// TODO(gri) should this be fromRHS for *Named?
+ // (See discussion in #66559.)
typ = under(typ)
}
}
package types_test
import (
+ "fmt"
"internal/testenv"
"strings"
"testing"
}
var testObjects = []struct {
- src string
- obj string
- want string
+ src string
+ obj string
+ want string
+ alias bool // needs materialized aliases
}{
- {"import \"io\"; var r io.Reader", "r", "var p.r io.Reader"},
+ {"import \"io\"; var r io.Reader", "r", "var p.r io.Reader", false},
- {"const c = 1.2", "c", "const p.c untyped float"},
- {"const c float64 = 3.14", "c", "const p.c float64"},
+ {"const c = 1.2", "c", "const p.c untyped float", false},
+ {"const c float64 = 3.14", "c", "const p.c float64", 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 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 = 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},
- {"var v int", "v", "var p.v int"},
+ {"var v int", "v", "var p.v int", 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 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 TestObjectString(t *testing.T) {
testenv.MustHaveGoBuild(t)
- for _, test := range testObjects {
- src := "package p; " + test.src
- pkg, err := typecheck(src, nil, nil)
- if err != nil {
- t.Errorf("%s: %s", src, err)
- continue
- }
+ for i, test := range testObjects {
+ t.Run(fmt.Sprint(i), func(t *testing.T) {
+ if test.alias {
+ t.Setenv("GODEBUG", "gotypesalias=1")
+ }
- names := strings.Split(test.obj, ".")
- if len(names) != 1 && len(names) != 2 {
- t.Errorf("%s: invalid object path %s", test.src, test.obj)
- continue
- }
- _, obj := pkg.Scope().LookupParent(names[0], nopos)
- if obj == nil {
- t.Errorf("%s: %s not found", test.src, names[0])
- continue
- }
- if len(names) == 2 {
- if typ, ok := obj.Type().(interface{ TypeParams() *TypeParamList }); ok {
- obj = lookupTypeParamObj(typ.TypeParams(), names[1])
- if obj == nil {
- t.Errorf("%s: %s not found", test.src, test.obj)
- continue
+ src := "package p; " + test.src
+ pkg, err := typecheck(src, nil, nil)
+ if err != nil {
+ t.Fatalf("%s: %s", src, err)
+ }
+
+ names := strings.Split(test.obj, ".")
+ if len(names) != 1 && len(names) != 2 {
+ t.Fatalf("%s: invalid object path %s", test.src, test.obj)
+ }
+ _, obj := pkg.Scope().LookupParent(names[0], nopos)
+ if obj == nil {
+ t.Fatalf("%s: %s not found", test.src, names[0])
+ }
+ if len(names) == 2 {
+ if typ, ok := obj.Type().(interface{ TypeParams() *TypeParamList }); ok {
+ obj = lookupTypeParamObj(typ.TypeParams(), names[1])
+ if obj == nil {
+ t.Fatalf("%s: %s not found", test.src, test.obj)
+ }
+ } else {
+ t.Fatalf("%s: %s has no type parameters", test.src, names[0])
}
- } else {
- t.Errorf("%s: %s has no type parameters", test.src, names[0])
- continue
}
- }
- if got := obj.String(); got != test.want {
- t.Errorf("%s: got %s, want %s", test.src, got, test.want)
- }
+ if got := obj.String(); got != test.want {
+ t.Errorf("%s: got %s, want %s", test.src, got, test.want)
+ }
+ })
}
}