1 // Copyright 2021 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
10 "internal/types/errors"
14 "cmd/compile/internal/base"
15 "cmd/compile/internal/rangefunc"
16 "cmd/compile/internal/syntax"
17 "cmd/compile/internal/types2"
21 var versionErrorRx = regexp.MustCompile(`requires go[0-9]+\.[0-9]+ or later`)
23 // checkFiles configures and runs the types2 checker on the given
24 // parsed source files and then returns the result.
25 func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
26 if base.SyntaxErrors() != 0 {
30 // setup and syntax error reporting
31 files := make([]*syntax.File, len(noders))
32 // posBaseMap maps all file pos bases back to *syntax.File
33 // for checking Go version mismatched.
34 posBaseMap := make(map[*syntax.PosBase]*syntax.File)
35 for i, p := range noders {
37 posBaseMap[p.file.Pos().Base()] = p.file
41 ctxt := types2.NewContext()
42 importer := gcimports{
44 packages: make(map[string]*types2.Package),
46 conf := types2.Config{
48 GoVersion: base.Flag.Lang,
49 IgnoreBranchErrors: true, // parser already checked via syntax.CheckBranches mode
51 Sizes: types2.SizesFor("gc", buildcfg.GOARCH),
53 if base.Flag.ErrorURL {
54 conf.ErrorURL = " [go.dev/e/%s]"
57 StoreTypesInSyntax: true,
58 Defs: make(map[*syntax.Name]types2.Object),
59 Uses: make(map[*syntax.Name]types2.Object),
60 Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
61 Implicits: make(map[syntax.Node]types2.Object),
62 Scopes: make(map[syntax.Node]*types2.Scope),
63 Instances: make(map[*syntax.Name]types2.Instance),
64 FileVersions: make(map[*syntax.PosBase]string),
67 conf.Error = func(err error) {
68 terr := err.(types2.Error)
70 if versionErrorRx.MatchString(msg) {
71 posBase := terr.Pos.Base()
72 for !posBase.IsFileBase() { // line directive base
73 posBase = posBase.Pos().Base()
75 fileVersion := info.FileVersions[posBase]
76 file := posBaseMap[posBase]
77 if file.GoVersion == fileVersion {
78 // If we have a version error caused by //go:build, report it.
79 msg = fmt.Sprintf("%s (file declares //go:build %s)", msg, fileVersion)
81 // Otherwise, hint at the -lang setting.
82 msg = fmt.Sprintf("%s (-lang was set to %s; check go.mod)", msg, base.Flag.Lang)
85 base.ErrorfAt(m.makeXPos(terr.Pos), terr.Code, "%s", msg)
88 pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info)
91 base.FatalfAt(src.NoXPos, "conf.Check error: %v", err)
94 // Check for anonymous interface cycles (#56103).
95 if base.Debug.InterfaceCycles == 0 {
97 for _, file := range files {
98 syntax.Inspect(file, func(n syntax.Node) bool {
99 if n, ok := n.(*syntax.InterfaceType); ok {
100 if f.hasCycle(n.GetTypeInfo().Type.(*types2.Interface)) {
101 base.ErrorfAt(m.makeXPos(n.Pos()), errors.InvalidTypeCycle, "invalid recursive type: anonymous interface refers to itself (see https://go.dev/issue/56103)")
103 for typ := range f.cyclic {
104 f.cyclic[typ] = false // suppress duplicate errors
115 // Implementation restriction: we don't allow not-in-heap types to
116 // be used as type arguments (#54765).
118 type nihTarg struct {
122 var nihTargs []nihTarg
124 for name, inst := range info.Instances {
125 for i := 0; i < inst.TypeArgs.Len(); i++ {
126 if targ := inst.TypeArgs.At(i); isNotInHeap(targ) {
127 nihTargs = append(nihTargs, nihTarg{m.makeXPos(name.Pos()), targ})
131 sort.Slice(nihTargs, func(i, j int) bool {
132 ti, tj := nihTargs[i], nihTargs[j]
133 return ti.pos.Before(tj.pos)
135 for _, targ := range nihTargs {
136 base.ErrorfAt(targ.pos, 0, "cannot use incomplete (or unallocatable) type as a type argument: %v", targ.typ)
141 // Rewrite range over function to explicit function calls
142 // with the loop bodies converted into new implicit closures.
143 // We do this now, before serialization to unified IR, so that if the
144 // implicit closures are inlined, we will have the unified IR form.
145 // If we do the rewrite in the back end, like between typecheck and walk,
146 // then the new implicit closure will not have a unified IR inline body,
147 // and bodyReaderFor will fail.
148 rangefunc.Rewrite(pkg, info, files)
153 // A cycleFinder detects anonymous interface cycles (go.dev/issue/56103).
154 type cycleFinder struct {
155 cyclic map[*types2.Interface]bool
158 // hasCycle reports whether typ is part of an anonymous interface cycle.
159 func (f *cycleFinder) hasCycle(typ *types2.Interface) bool {
160 // We use Method instead of ExplicitMethod to implicitly expand any
161 // embedded interfaces. Then we just need to walk any anonymous
162 // types, keeping track of *types2.Interface types we visit along
164 for i := 0; i < typ.NumMethods(); i++ {
165 if f.visit(typ.Method(i).Type()) {
172 // visit recursively walks typ0 to check any referenced interface types.
173 func (f *cycleFinder) visit(typ0 types2.Type) bool {
174 for { // loop for tail recursion
175 switch typ := typ0.(type) {
177 base.Fatalf("unexpected type: %T", typ)
179 case *types2.Basic, *types2.Named, *types2.TypeParam:
180 return false // named types cannot be part of an anonymous cycle
181 case *types2.Pointer:
188 if f.visit(typ.Key()) {
196 for i := 0; i < typ.NumFields(); i++ {
197 if f.visit(typ.Field(i).Type()) {
203 case *types2.Interface:
204 // The empty interface (e.g., "any") cannot be part of a cycle.
205 if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 0 {
209 // As an optimization, we wait to allocate cyclic here, after
210 // we've found at least one other (non-empty) anonymous
211 // interface. This means when a cycle is present, we need to
212 // make an extra recursive call to actually detect it. But for
213 // most packages, it allows skipping the map allocation
215 if x, ok := f.cyclic[typ]; ok {
219 f.cyclic = make(map[*types2.Interface]bool)
225 f.cyclic[typ] = false
228 case *types2.Signature:
229 return f.visit(typ.Params()) || f.visit(typ.Results())
231 for i := 0; i < typ.Len(); i++ {
232 if f.visit(typ.At(i).Type()) {