1
2
3
4
5 package noder
6
7 import (
8 "fmt"
9 "internal/buildcfg"
10 "internal/types/errors"
11 "regexp"
12 "sort"
13
14 "cmd/compile/internal/base"
15 "cmd/compile/internal/rangefunc"
16 "cmd/compile/internal/syntax"
17 "cmd/compile/internal/types2"
18 "cmd/internal/src"
19 )
20
21 var versionErrorRx = regexp.MustCompile(`requires go[0-9]+\.[0-9]+ or later`)
22
23
24
25 func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
26 if base.SyntaxErrors() != 0 {
27 base.ErrorExit()
28 }
29
30
31 files := make([]*syntax.File, len(noders))
32
33
34 posBaseMap := make(map[*syntax.PosBase]*syntax.File)
35 for i, p := range noders {
36 files[i] = p.file
37 posBaseMap[p.file.Pos().Base()] = p.file
38 }
39
40
41 ctxt := types2.NewContext()
42 importer := gcimports{
43 ctxt: ctxt,
44 packages: make(map[string]*types2.Package),
45 }
46 conf := types2.Config{
47 Context: ctxt,
48 GoVersion: base.Flag.Lang,
49 IgnoreBranchErrors: true,
50 Importer: &importer,
51 Sizes: types2.SizesFor("gc", buildcfg.GOARCH),
52 EnableAlias: true,
53 }
54 if base.Flag.ErrorURL {
55 conf.ErrorURL = " [go.dev/e/%s]"
56 }
57 info := &types2.Info{
58 StoreTypesInSyntax: true,
59 Defs: make(map[*syntax.Name]types2.Object),
60 Uses: make(map[*syntax.Name]types2.Object),
61 Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
62 Implicits: make(map[syntax.Node]types2.Object),
63 Scopes: make(map[syntax.Node]*types2.Scope),
64 Instances: make(map[*syntax.Name]types2.Instance),
65 FileVersions: make(map[*syntax.PosBase]string),
66
67 }
68 conf.Error = func(err error) {
69 terr := err.(types2.Error)
70 msg := terr.Msg
71 if versionErrorRx.MatchString(msg) {
72 posBase := terr.Pos.Base()
73 for !posBase.IsFileBase() {
74 posBase = posBase.Pos().Base()
75 }
76 fileVersion := info.FileVersions[posBase]
77 file := posBaseMap[posBase]
78 if file.GoVersion == fileVersion {
79
80 msg = fmt.Sprintf("%s (file declares //go:build %s)", msg, fileVersion)
81 } else {
82
83 msg = fmt.Sprintf("%s (-lang was set to %s; check go.mod)", msg, base.Flag.Lang)
84 }
85 }
86 base.ErrorfAt(m.makeXPos(terr.Pos), terr.Code, "%s", msg)
87 }
88
89 pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info)
90 base.ExitIfErrors()
91 if err != nil {
92 base.FatalfAt(src.NoXPos, "conf.Check error: %v", err)
93 }
94
95
96
97 var f cycleFinder
98 for _, file := range files {
99 syntax.Inspect(file, func(n syntax.Node) bool {
100 if n, ok := n.(*syntax.InterfaceType); ok {
101 if f.hasCycle(types2.Unalias(n.GetTypeInfo().Type).(*types2.Interface)) {
102 base.ErrorfAt(m.makeXPos(n.Pos()), errors.InvalidTypeCycle, "invalid recursive type: anonymous interface refers to itself (see https://go.dev/issue/56103)")
103
104 for typ := range f.cyclic {
105 f.cyclic[typ] = false
106 }
107 }
108 return false
109 }
110 return true
111 })
112 }
113 base.ExitIfErrors()
114
115
116
117 {
118 type nihTarg struct {
119 pos src.XPos
120 typ types2.Type
121 }
122 var nihTargs []nihTarg
123
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})
128 }
129 }
130 }
131 sort.Slice(nihTargs, func(i, j int) bool {
132 ti, tj := nihTargs[i], nihTargs[j]
133 return ti.pos.Before(tj.pos)
134 })
135 for _, targ := range nihTargs {
136 base.ErrorfAt(targ.pos, 0, "cannot use incomplete (or unallocatable) type as a type argument: %v", targ.typ)
137 }
138 }
139 base.ExitIfErrors()
140
141
142
143
144
145
146
147
148 rangefunc.Rewrite(pkg, info, files)
149
150 return pkg, info
151 }
152
153
154 type cycleFinder struct {
155 cyclic map[*types2.Interface]bool
156 }
157
158
159 func (f *cycleFinder) hasCycle(typ *types2.Interface) bool {
160
161
162
163
164 for i := 0; i < typ.NumMethods(); i++ {
165 if f.visit(typ.Method(i).Type()) {
166 return true
167 }
168 }
169 return false
170 }
171
172
173 func (f *cycleFinder) visit(typ0 types2.Type) bool {
174 for {
175 switch typ := types2.Unalias(typ0).(type) {
176 default:
177 base.Fatalf("unexpected type: %T", typ)
178
179 case *types2.Basic, *types2.Named, *types2.TypeParam:
180 return false
181 case *types2.Pointer:
182 typ0 = typ.Elem()
183 case *types2.Array:
184 typ0 = typ.Elem()
185 case *types2.Chan:
186 typ0 = typ.Elem()
187 case *types2.Map:
188 if f.visit(typ.Key()) {
189 return true
190 }
191 typ0 = typ.Elem()
192 case *types2.Slice:
193 typ0 = typ.Elem()
194
195 case *types2.Struct:
196 for i := 0; i < typ.NumFields(); i++ {
197 if f.visit(typ.Field(i).Type()) {
198 return true
199 }
200 }
201 return false
202
203 case *types2.Interface:
204
205 if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 0 {
206 return false
207 }
208
209
210
211
212
213
214
215 if x, ok := f.cyclic[typ]; ok {
216 return x
217 }
218 if f.cyclic == nil {
219 f.cyclic = make(map[*types2.Interface]bool)
220 }
221 f.cyclic[typ] = true
222 if f.hasCycle(typ) {
223 return true
224 }
225 f.cyclic[typ] = false
226 return false
227
228 case *types2.Signature:
229 return f.visit(typ.Params()) || f.visit(typ.Results())
230 case *types2.Tuple:
231 for i := 0; i < typ.Len(); i++ {
232 if f.visit(typ.At(i).Type()) {
233 return true
234 }
235 }
236 return false
237 }
238 }
239 }
240
View as plain text