Skip to content

Commit 3395f74

Browse files
committed
go/types, types2: implement flexible flag-setting mechanism for tests
Use it so set the language version. Adjust relevant tests. Fixes golang#49074. Change-Id: Ida6d0002bdba65b5add6e8728a1700305de18351 Reviewed-on: https://go-review.googlesource.com/c/go/+/393514 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
1 parent 6be52ab commit 3395f74

File tree

18 files changed

+139
-54
lines changed

18 files changed

+139
-54
lines changed

src/cmd/compile/internal/types2/check_test.go

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
package types2_test
2424

2525
import (
26+
"bytes"
2627
"cmd/compile/internal/syntax"
2728
"flag"
29+
"fmt"
2830
"internal/testenv"
2931
"os"
3032
"path/filepath"
@@ -79,25 +81,60 @@ func delta(x, y uint) uint {
7981
}
8082
}
8183

82-
// goVersionRx matches a Go version string using '_', e.g. "go1_12".
83-
var goVersionRx = regexp.MustCompile(`^go[1-9][0-9]*_(0|[1-9][0-9]*)$`)
84+
// Note: parseFlags is identical to the version in go/types which is
85+
// why it has a src argument even though here it is always nil.
86+
87+
// parseFlags parses flags from the first line of the given source
88+
// (from src if present, or by reading from the file) if the line
89+
// starts with "//" (line comment) followed by "-" (possiby with
90+
// spaces between). Otherwise the line is ignored.
91+
func parseFlags(filename string, src []byte, flags *flag.FlagSet) error {
92+
// If there is no src, read from the file.
93+
const maxLen = 256
94+
if len(src) == 0 {
95+
f, err := os.Open(filename)
96+
if err != nil {
97+
return err
98+
}
99+
100+
var buf [maxLen]byte
101+
n, err := f.Read(buf[:])
102+
if err != nil {
103+
return err
104+
}
105+
src = buf[:n]
106+
}
84107

85-
// asGoVersion returns a regular Go language version string
86-
// if s is a Go version string using '_' rather than '.' to
87-
// separate the major and minor version numbers (e.g. "go1_12").
88-
// Otherwise it returns the empty string.
89-
func asGoVersion(s string) string {
90-
if goVersionRx.MatchString(s) {
91-
return strings.Replace(s, "_", ".", 1)
108+
// we must have a line comment that starts with a "-"
109+
const prefix = "//"
110+
if !bytes.HasPrefix(src, []byte(prefix)) {
111+
return nil // first line is not a line comment
112+
}
113+
src = src[len(prefix):]
114+
if i := bytes.Index(src, []byte("-")); i < 0 || len(bytes.TrimSpace(src[:i])) != 0 {
115+
return nil // comment doesn't start with a "-"
92116
}
93-
return ""
117+
end := bytes.Index(src, []byte("\n"))
118+
if end < 0 || end > maxLen {
119+
return fmt.Errorf("flags comment line too long")
120+
}
121+
122+
return flags.Parse(strings.Fields(string(src[:end])))
94123
}
95124

96125
func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) {
97126
if len(filenames) == 0 {
98127
t.Fatal("no source files")
99128
}
100129

130+
var conf Config
131+
flags := flag.NewFlagSet("", flag.PanicOnError)
132+
flags.StringVar(&conf.GoVersion, "lang", "", "")
133+
if err := parseFlags(filenames[0], nil, flags); err != nil {
134+
t.Fatal(err)
135+
}
136+
137+
// TODO(gri) remove this or use flag mechanism to set mode if still needed
101138
var mode syntax.Mode
102139
if strings.HasSuffix(filenames[0], ".go2") || manual {
103140
mode |= syntax.AllowGenerics | syntax.AllowMethodTypeParams
@@ -110,12 +147,6 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) {
110147
pkgName = files[0].PkgName.Value
111148
}
112149

113-
// if no Go version is given, consider the package name
114-
goVersion := *goVersion
115-
if goVersion == "" {
116-
goVersion = asGoVersion(pkgName)
117-
}
118-
119150
listErrors := manual && !*verifyErrors
120151
if listErrors && len(errlist) > 0 {
121152
t.Errorf("--- %s:", pkgName)
@@ -125,8 +156,6 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) {
125156
}
126157

127158
// typecheck and collect typechecker errors
128-
var conf Config
129-
conf.GoVersion = goVersion
130159
// special case for importC.src
131160
if len(filenames) == 1 && strings.HasSuffix(filenames[0], "importC.src") {
132161
conf.FakeImportC = true

src/cmd/compile/internal/types2/testdata/check/decls0.src

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
// -lang=go1.17
2+
13
// Copyright 2011 The Go Authors. All rights reserved.
24
// Use of this source code is governed by a BSD-style
35
// license that can be found in the LICENSE file.
46

57
// type declarations
68

7-
package go1_17 // don't permit non-interface elements in interfaces
9+
package p // don't permit non-interface elements in interfaces
810

911
import "unsafe"
1012

src/cmd/compile/internal/types2/testdata/check/go1_12.src

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
// -lang=go1.12
2+
13
// Copyright 2021 The Go Authors. All rights reserved.
24
// Use of this source code is governed by a BSD-style
35
// license that can be found in the LICENSE file.
46

57
// Check Go language version-specific errors.
68

7-
package go1_12 // go1.12
9+
package p
810

911
// numeric literals
1012
const (

src/cmd/compile/internal/types2/testdata/check/go1_13.src

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
// -lang=go1.13
2+
13
// Copyright 2021 The Go Authors. All rights reserved.
24
// Use of this source code is governed by a BSD-style
35
// license that can be found in the LICENSE file.
46

57
// Check Go language version-specific errors.
68

7-
package go1_13 // go1.13
9+
package p
810

911
// interface embedding
1012

src/cmd/compile/internal/types2/testdata/check/go1_16.src

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
// -lang=go1.16
2+
13
// Copyright 2021 The Go Authors. All rights reserved.
24
// Use of this source code is governed by a BSD-style
35
// license that can be found in the LICENSE file.
46

57
// Check Go language version-specific errors.
68

7-
package go1_16 // go1.16
9+
package p
810

911
type Slice []byte
1012
type Array [8]byte
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
// -lang=go1.8
2+
13
// Copyright 2021 The Go Authors. All rights reserved.
24
// Use of this source code is governed by a BSD-style
35
// license that can be found in the LICENSE file.
46

57
// Check Go language version-specific errors.
68

7-
package go1_8 // go1.8
9+
package p
810

911
// type alias declarations
1012
type any /* ERROR type aliases requires go1.9 or later */ = interface{}

src/cmd/compile/internal/types2/testdata/check/issues.src

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
// -lang=go1.17
2+
13
// Copyright 2014 The Go Authors. All rights reserved.
24
// Use of this source code is governed by a BSD-style
35
// license that can be found in the LICENSE file.
46

5-
package go1_17 // don't permit non-interface elements in interfaces
7+
package p // don't permit non-interface elements in interfaces
68

79
import (
810
"fmt"
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
// -lang=go1.17
2+
13
// Copyright 2020 The Go Authors. All rights reserved.
24
// Use of this source code is governed by a BSD-style
35
// license that can be found in the LICENSE file.
46

57
// The predeclared type comparable is not visible before Go 1.18.
68

7-
package go1_17
9+
package p
810

911
type _ comparable // ERROR undeclared

src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// -lang=go1.17
2+
13
// Copyright 2021 The Go Authors. All rights reserved.
24
// Use of this source code is governed by a BSD-style
35
// license that can be found in the LICENSE file.
@@ -6,7 +8,7 @@
68
// needs to report any operations that are not permitted
79
// before Go 1.18.
810

9-
package go1_17
11+
package p
1012

1113
type T[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
1214

src/go/types/check_test.go

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
package types_test
2424

2525
import (
26+
"bytes"
2627
"flag"
2728
"fmt"
2829
"go/ast"
@@ -185,25 +186,58 @@ func eliminate(t *testing.T, errmap map[string][]string, errlist []error) {
185186
}
186187
}
187188

188-
// goVersionRx matches a Go version string using '_', e.g. "go1_12".
189-
var goVersionRx = regexp.MustCompile(`^go[1-9][0-9]*_(0|[1-9][0-9]*)$`)
189+
// parseFlags parses flags from the first line of the given source
190+
// (from src if present, or by reading from the file) if the line
191+
// starts with "//" (line comment) followed by "-" (possiby with
192+
// spaces between). Otherwise the line is ignored.
193+
func parseFlags(filename string, src []byte, flags *flag.FlagSet) error {
194+
// If there is no src, read from the file.
195+
const maxLen = 256
196+
if len(src) == 0 {
197+
f, err := os.Open(filename)
198+
if err != nil {
199+
return err
200+
}
190201

191-
// asGoVersion returns a regular Go language version string
192-
// if s is a Go version string using '_' rather than '.' to
193-
// separate the major and minor version numbers (e.g. "go1_12").
194-
// Otherwise it returns the empty string.
195-
func asGoVersion(s string) string {
196-
if goVersionRx.MatchString(s) {
197-
return strings.Replace(s, "_", ".", 1)
202+
var buf [maxLen]byte
203+
n, err := f.Read(buf[:])
204+
if err != nil {
205+
return err
206+
}
207+
src = buf[:n]
198208
}
199-
return ""
209+
210+
// we must have a line comment that starts with a "-"
211+
const prefix = "//"
212+
if !bytes.HasPrefix(src, []byte(prefix)) {
213+
return nil // first line is not a line comment
214+
}
215+
src = src[len(prefix):]
216+
if i := bytes.Index(src, []byte("-")); i < 0 || len(bytes.TrimSpace(src[:i])) != 0 {
217+
return nil // comment doesn't start with a "-"
218+
}
219+
end := bytes.Index(src, []byte("\n"))
220+
if end < 0 || end > maxLen {
221+
return fmt.Errorf("flags comment line too long")
222+
}
223+
224+
return flags.Parse(strings.Fields(string(src[:end])))
200225
}
201226

202227
func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, manual bool, imp Importer) {
203228
if len(filenames) == 0 {
204229
t.Fatal("no source files")
205230
}
206231

232+
var conf Config
233+
conf.Sizes = sizes
234+
flags := flag.NewFlagSet("", flag.PanicOnError)
235+
flags.StringVar(&conf.GoVersion, "lang", "", "")
236+
if err := parseFlags(filenames[0], srcs[0], flags); err != nil {
237+
t.Fatal(err)
238+
}
239+
240+
// TODO(gri) remove this or use flag mechanism to set mode if still needed
207241
if strings.HasSuffix(filenames[0], ".go1") {
208242
// TODO(rfindley): re-enable this test by using GoVersion.
209243
t.Skip("type params are enabled")
@@ -222,12 +256,6 @@ func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, man
222256
pkgName = files[0].Name.Name
223257
}
224258

225-
// if no Go version is given, consider the package name
226-
goVersion := *goVersion
227-
if goVersion == "" {
228-
goVersion = asGoVersion(pkgName)
229-
}
230-
231259
listErrors := manual && !*verifyErrors
232260
if listErrors && len(errlist) > 0 {
233261
t.Errorf("--- %s:", pkgName)
@@ -237,10 +265,6 @@ func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, man
237265
}
238266

239267
// typecheck and collect typechecker errors
240-
var conf Config
241-
conf.Sizes = sizes
242-
conf.GoVersion = goVersion
243-
244268
// special case for importC.src
245269
if len(filenames) == 1 {
246270
if strings.HasSuffix(filenames[0], "importC.src") {

0 commit comments

Comments
 (0)