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 for i, p := range noders {
37 ctxt := types2.NewContext()
38 importer := gcimports{
40 packages: make(map[string]*types2.Package),
42 conf := types2.Config{
44 GoVersion: base.Flag.Lang,
45 IgnoreBranchErrors: true, // parser already checked via syntax.CheckBranches mode
46 Error: func(err error) {
47 terr := err.(types2.Error)
49 // if we have a version error, hint at the -lang setting
50 if versionErrorRx.MatchString(msg) {
51 msg = fmt.Sprintf("%s (-lang was set to %s; check go.mod)", msg, base.Flag.Lang)
53 base.ErrorfAt(m.makeXPos(terr.Pos), terr.Code, "%s", msg)
56 Sizes: types2.SizesFor("gc", buildcfg.GOARCH),
58 if base.Flag.ErrorURL {
59 conf.ErrorURL = " [go.dev/e/%s]"
62 StoreTypesInSyntax: true,
63 Defs: make(map[*syntax.Name]types2.Object),
64 Uses: make(map[*syntax.Name]types2.Object),
65 Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
66 Implicits: make(map[syntax.Node]types2.Object),
67 Scopes: make(map[syntax.Node]*types2.Scope),
68 Instances: make(map[*syntax.Name]types2.Instance),
69 FileVersions: make(map[*syntax.PosBase]types2.Version),
73 pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info)
76 base.FatalfAt(src.NoXPos, "conf.Check error: %v", err)
79 // Check for anonymous interface cycles (#56103).
80 if base.Debug.InterfaceCycles == 0 {
82 for _, file := range files {
83 syntax.Inspect(file, func(n syntax.Node) bool {
84 if n, ok := n.(*syntax.InterfaceType); ok {
85 if f.hasCycle(n.GetTypeInfo().Type.(*types2.Interface)) {
86 base.ErrorfAt(m.makeXPos(n.Pos()), errors.InvalidTypeCycle, "invalid recursive type: anonymous interface refers to itself (see https://go.dev/issue/56103)")
88 for typ := range f.cyclic {
89 f.cyclic[typ] = false // suppress duplicate errors
100 // Implementation restriction: we don't allow not-in-heap types to
101 // be used as type arguments (#54765).
103 type nihTarg struct {
107 var nihTargs []nihTarg
109 for name, inst := range info.Instances {
110 for i := 0; i < inst.TypeArgs.Len(); i++ {
111 if targ := inst.TypeArgs.At(i); isNotInHeap(targ) {
112 nihTargs = append(nihTargs, nihTarg{m.makeXPos(name.Pos()), targ})
116 sort.Slice(nihTargs, func(i, j int) bool {
117 ti, tj := nihTargs[i], nihTargs[j]
118 return ti.pos.Before(tj.pos)
120 for _, targ := range nihTargs {
121 base.ErrorfAt(targ.pos, 0, "cannot use incomplete (or unallocatable) type as a type argument: %v", targ.typ)
126 // Rewrite range over function to explicit function calls
127 // with the loop bodies converted into new implicit closures.
128 // We do this now, before serialization to unified IR, so that if the
129 // implicit closures are inlined, we will have the unified IR form.
130 // If we do the rewrite in the back end, like between typecheck and walk,
131 // then the new implicit closure will not have a unified IR inline body,
132 // and bodyReaderFor will fail.
133 rangefunc.Rewrite(pkg, info, files)
138 // A cycleFinder detects anonymous interface cycles (go.dev/issue/56103).
139 type cycleFinder struct {
140 cyclic map[*types2.Interface]bool
143 // hasCycle reports whether typ is part of an anonymous interface cycle.
144 func (f *cycleFinder) hasCycle(typ *types2.Interface) bool {
145 // We use Method instead of ExplicitMethod to implicitly expand any
146 // embedded interfaces. Then we just need to walk any anonymous
147 // types, keeping track of *types2.Interface types we visit along
149 for i := 0; i < typ.NumMethods(); i++ {
150 if f.visit(typ.Method(i).Type()) {
157 // visit recursively walks typ0 to check any referenced interface types.
158 func (f *cycleFinder) visit(typ0 types2.Type) bool {
159 for { // loop for tail recursion
160 switch typ := typ0.(type) {
162 base.Fatalf("unexpected type: %T", typ)
164 case *types2.Basic, *types2.Named, *types2.TypeParam:
165 return false // named types cannot be part of an anonymous cycle
166 case *types2.Pointer:
173 if f.visit(typ.Key()) {
181 for i := 0; i < typ.NumFields(); i++ {
182 if f.visit(typ.Field(i).Type()) {
188 case *types2.Interface:
189 // The empty interface (e.g., "any") cannot be part of a cycle.
190 if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 0 {
194 // As an optimization, we wait to allocate cyclic here, after
195 // we've found at least one other (non-empty) anonymous
196 // interface. This means when a cycle is present, we need to
197 // make an extra recursive call to actually detect it. But for
198 // most packages, it allows skipping the map allocation
200 if x, ok := f.cyclic[typ]; ok {
204 f.cyclic = make(map[*types2.Interface]bool)
210 f.cyclic[typ] = false
213 case *types2.Signature:
214 return f.visit(typ.Params()) || f.visit(typ.Results())
216 for i := 0; i < typ.Len(); i++ {
217 if f.visit(typ.At(i).Type()) {