diff options
Diffstat (limited to 'src/go/types/check.go')
-rw-r--r-- | src/go/types/check.go | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/src/go/types/check.go b/src/go/types/check.go index 5381b5db68..3b0f5e4fdf 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -12,6 +12,7 @@ import ( "go/ast" "go/constant" "go/token" + "internal/goversion" . "internal/types/errors" ) @@ -233,20 +234,20 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch info = new(Info) } - version, err := parseGoVersion(conf.GoVersion) - if err != nil { - panic(fmt.Sprintf("invalid Go version %q (%v)", conf.GoVersion, err)) - } + // Note: clients may call NewChecker with the Unsafe package, which is + // globally shared and must not be mutated. Therefore NewChecker must not + // mutate *pkg. + // + // (previously, pkg.goVersion was mutated here: go.dev/issue/61212) return &Checker{ - conf: conf, - ctxt: conf.Context, - fset: fset, - pkg: pkg, - Info: info, - version: version, - objMap: make(map[Object]*declInfo), - impMap: make(map[importKey]*Package), + conf: conf, + ctxt: conf.Context, + fset: fset, + pkg: pkg, + Info: info, + objMap: make(map[Object]*declInfo), + impMap: make(map[importKey]*Package), } } @@ -342,6 +343,20 @@ func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(f var errBadCgo = errors.New("cannot use FakeImportC and go115UsesCgo together") func (check *Checker) checkFiles(files []*ast.File) (err error) { + if check.pkg == Unsafe { + // Defensive handling for Unsafe, which cannot be type checked, and must + // not be mutated. See https://go.dev/issue/61212 for an example of where + // Unsafe is passed to NewChecker. + return nil + } + + check.version, err = parseGoVersion(check.conf.GoVersion) + if err != nil { + return err + } + if check.version.after(version{1, goversion.Version}) { + return fmt.Errorf("package requires newer Go version %v", check.version) + } if check.conf.FakeImportC && check.conf.go115UsesCgo { return errBadCgo } @@ -386,6 +401,7 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.monomorph() } + check.pkg.goVersion = check.conf.GoVersion check.pkg.complete = true // no longer needed - release memory |