Like for Named types, print type parameters for Alias types.
Add test case for Alias object string to existing test.
To make the test work, factor out the mechanism to set
GOEXPERIMENT=aliastypeparams at test time and use it
for this test as well.
No test case for un-instantiated generic type Alias type
string: there's no existing test framework, the code is
identical as for Named types, and these strings only appear
in tracing output. Tested manually.
Change-Id: I476d04d0b6a7c18b79be1d34a9e3e072941df83f
Reviewed-on: https://go-review.googlesource.com/c/go/+/615195
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Tim King <taking@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
t.Fatal(err)
}
- exp, err := buildcfg.ParseGOEXPERIMENT(runtime.GOOS, runtime.GOARCH, goexperiment)
- if err != nil {
- t.Fatal(err)
+ if goexperiment != "" {
+ defer setGOEXPERIMENT(goexperiment)()
}
- old := buildcfg.Experiment
- defer func() {
- buildcfg.Experiment = old
- }()
- buildcfg.Experiment = *exp
// By default, gotypesalias is not set.
if gotypesalias != "" {
return (*bool)(v.FieldByName(name).Addr().UnsafePointer())
}
+// setGOEXPERIMENT overwrites the existing buildcfg.Experiment with a new one
+// based on the provided goexperiment string. Calling the result function
+// (typically via defer), reverts buildcfg.Experiment to the prior value.
+// For testing use, only.
+func setGOEXPERIMENT(goexperiment string) func() {
+ exp, err := buildcfg.ParseGOEXPERIMENT(runtime.GOOS, runtime.GOARCH, goexperiment)
+ if err != nil {
+ panic(err)
+ }
+ old := buildcfg.Experiment
+ buildcfg.Experiment = *exp
+ return func() {
+ buildcfg.Experiment = old
+ }
+}
+
// TestManual is for manual testing of a package - either provided
// as a list of filenames belonging to the package, or a directory
// name containing the package files - after the test arguments
// Don't print anything more for basic types since there's
// no more information.
return
- case *Named:
+ case genericType:
if t.TypeParams().Len() > 0 {
newTypeWriter(buf, qf).tParamList(t.TypeParams().list())
}
src string
obj string
want string
- alias bool // needs materialized aliases
+ alias bool // needs materialized (and possibly generic) aliases
}{
{"import \"io\"; var r io.Reader", "r", "var p.r io.Reader", false},
{"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}, // requires GOEXPERIMENT=aliastypeparams
{"var v int", "v", "var p.v int", false},
for i, test := range testObjects {
t.Run(fmt.Sprint(i), func(t *testing.T) {
+ if test.alias {
+ defer setGOEXPERIMENT("aliastypeparams")()
+ }
src := "package p; " + test.src
conf := Config{Error: func(error) {}, Importer: defaultImporter(), EnableAlias: test.alias}
pkg, err := typecheck(src, &conf, nil)
if list := t.targs.list(); len(list) != 0 {
// instantiated type
w.typeList(list)
+ } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TypeParams
+ // parameterized type
+ w.tParamList(t.TypeParams().list())
}
if w.ctxt != nil {
// TODO(gri) do we need to print the alias type name, too?
t.Fatal(err)
}
- exp, err := buildcfg.ParseGOEXPERIMENT(runtime.GOOS, runtime.GOARCH, goexperiment)
- if err != nil {
- t.Fatal(err)
+ if goexperiment != "" {
+ defer setGOEXPERIMENT(goexperiment)()
}
- old := buildcfg.Experiment
- defer func() {
- buildcfg.Experiment = old
- }()
- buildcfg.Experiment = *exp
// By default, gotypesalias is not set.
if gotypesalias != "" {
return (*string)(v.FieldByName(name).Addr().UnsafePointer())
}
+// setGOEXPERIMENT overwrites the existing buildcfg.Experiment with a new one
+// based on the provided goexperiment string. Calling the result function
+// (typically via defer), reverts buildcfg.Experiment to the prior value.
+// For testing use, only.
+func setGOEXPERIMENT(goexperiment string) func() {
+ exp, err := buildcfg.ParseGOEXPERIMENT(runtime.GOOS, runtime.GOARCH, goexperiment)
+ if err != nil {
+ panic(err)
+ }
+ old := buildcfg.Experiment
+ buildcfg.Experiment = *exp
+ return func() {
+ buildcfg.Experiment = old
+ }
+}
+
// TestManual is for manual testing of a package - either provided
// as a list of filenames belonging to the package, or a directory
// name containing the package files - after the test arguments
// Don't print anything more for basic types since there's
// no more information.
return
- case *Named:
+ case genericType:
if t.TypeParams().Len() > 0 {
newTypeWriter(buf, qf).tParamList(t.TypeParams().list())
}
src string
obj string
want string
- alias bool // needs materialized aliases
+ alias bool // needs materialized (and possibly generic) aliases
}{
{"import \"io\"; var r io.Reader", "r", "var p.r io.Reader", false},
{"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}, // requires GOEXPERIMENT=aliastypeparams
{"var v int", "v", "var p.v int", false},
for i, test := range testObjects {
t.Run(fmt.Sprint(i), func(t *testing.T) {
if test.alias {
+ defer setGOEXPERIMENT("aliastypeparams")()
t.Setenv("GODEBUG", "gotypesalias=1")
}
if list := t.targs.list(); len(list) != 0 {
// instantiated type
w.typeList(list)
+ } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TypeParams
+ // parameterized type
+ w.tParamList(t.TypeParams().list())
}
if w.ctxt != nil {
// TODO(gri) do we need to print the alias type name, too?