Source file src/go/types/decl.go
1
2
3
4
5 package types
6
7 import (
8 "go/ast"
9 "go/constant"
10 "go/token"
11 )
12
13 func (check *Checker) reportAltDecl(obj Object) {
14 if pos := obj.Pos(); pos.IsValid() {
15
16
17
18 check.errorf(pos, "\tother declaration of %s", obj.Name())
19 }
20 }
21
22 func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object, pos token.Pos) {
23
24
25
26
27 if obj.Name() != "_" {
28 if alt := scope.Insert(obj); alt != nil {
29 check.errorf(obj.Pos(), "%s redeclared in this block", obj.Name())
30 check.reportAltDecl(alt)
31 return
32 }
33 obj.setScopePos(pos)
34 }
35 if id != nil {
36 check.recordDef(id, obj)
37 }
38 }
39
40
41
42
43 func pathString(path []*TypeName) string {
44 var s string
45 for i, p := range path {
46 if i > 0 {
47 s += "->"
48 }
49 s += p.Name()
50 }
51 return s
52 }
53
54
55
56 func objPathString(path []Object) string {
57 var s string
58 for i, p := range path {
59 if i > 0 {
60 s += "->"
61 }
62 s += p.Name()
63 }
64 return s
65 }
66
67
68
69 func (check *Checker) objDecl(obj Object, def *Named) {
70 if trace {
71 check.trace(obj.Pos(), "-- checking %s %s (objPath = %s)", obj.color(), obj, objPathString(check.objPath))
72 check.indent++
73 defer func() {
74 check.indent--
75 check.trace(obj.Pos(), "=> %s", obj)
76 }()
77 }
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 if obj.color() == white && obj.Type() != nil {
107 obj.setColor(black)
108 return
109 }
110
111 switch obj.color() {
112 case white:
113 assert(obj.Type() == nil)
114
115
116
117 obj.setColor(grey + color(check.push(obj)))
118 defer func() {
119 check.pop().setColor(black)
120 }()
121
122 case black:
123 assert(obj.Type() != nil)
124 return
125
126 default:
127
128 fallthrough
129
130 case grey:
131
132
133
134
135
136
137
138
139
140
141 switch obj := obj.(type) {
142 case *Const:
143 if check.typeCycle(obj) || obj.typ == nil {
144 obj.typ = Typ[Invalid]
145 }
146
147 case *Var:
148 if check.typeCycle(obj) || obj.typ == nil {
149 obj.typ = Typ[Invalid]
150 }
151
152 case *TypeName:
153 if check.typeCycle(obj) {
154
155
156
157
158
159 obj.typ = Typ[Invalid]
160 }
161
162 case *Func:
163 if check.typeCycle(obj) {
164
165
166
167
168
169
170 }
171
172 default:
173 unreachable()
174 }
175 assert(obj.Type() != nil)
176 return
177 }
178
179 d := check.objMap[obj]
180 if d == nil {
181 check.dump("%v: %s should have been declared", obj.Pos(), obj)
182 unreachable()
183 }
184
185
186 defer func(ctxt context) {
187 check.context = ctxt
188 }(check.context)
189 check.context = context{
190 scope: d.file,
191 }
192
193
194
195
196
197
198 switch obj := obj.(type) {
199 case *Const:
200 check.decl = d
201 check.constDecl(obj, d.typ, d.init)
202 case *Var:
203 check.decl = d
204 check.varDecl(obj, d.lhs, d.typ, d.init)
205 case *TypeName:
206
207 check.typeDecl(obj, d.typ, def, d.alias)
208 case *Func:
209
210 check.funcDecl(obj, d)
211 default:
212 unreachable()
213 }
214 }
215
216
217
218
219
220
221 var indir = NewTypeName(token.NoPos, nil, "*", nil)
222
223
224
225
226
227 func (check *Checker) typeCycle(obj Object) (isCycle bool) {
228
229 if debug {
230 info := check.objMap[obj]
231 inObjMap := info != nil && (info.fdecl == nil || info.fdecl.Recv == nil)
232 isPkgObj := obj.Parent() == check.pkg.scope
233 if isPkgObj != inObjMap {
234 check.dump("%v: inconsistent object map for %s (isPkgObj = %v, inObjMap = %v)", obj.Pos(), obj, isPkgObj, inObjMap)
235 unreachable()
236 }
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252 var nval, ncycle int
253 var hasIndir, hasTDef bool
254 assert(obj.color() >= grey)
255 start := obj.color() - grey
256 cycle := check.objPath[start:]
257 ncycle = len(cycle)
258 for _, obj := range cycle {
259 switch obj := obj.(type) {
260 case *Const, *Var:
261 nval++
262 case *TypeName:
263 if obj == indir {
264 ncycle--
265 hasIndir = true
266 } else {
267
268
269
270
271
272
273
274
275
276 var alias bool
277 if d := check.objMap[obj]; d != nil {
278 alias = d.alias
279 } else {
280 alias = obj.IsAlias()
281 }
282 if !alias {
283 hasTDef = true
284 }
285 }
286 case *Func:
287
288 default:
289 unreachable()
290 }
291 }
292
293 if trace {
294 check.trace(obj.Pos(), "## cycle detected: objPath = %s->%s (len = %d)", objPathString(cycle), obj.Name(), ncycle)
295 check.trace(obj.Pos(), "## cycle contains: %d values, has indirection = %v, has type definition = %v", nval, hasIndir, hasTDef)
296 defer func() {
297 if isCycle {
298 check.trace(obj.Pos(), "=> error: cycle is invalid")
299 }
300 }()
301 }
302
303
304
305
306 if nval == ncycle {
307 return false
308 }
309
310
311
312
313
314
315 if nval == 0 && hasIndir && hasTDef {
316 return false
317 }
318
319
320 check.errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name())
321 for _, obj := range cycle {
322 if obj == indir {
323 continue
324 }
325 check.errorf(obj.Pos(), "\t%s refers to", obj.Name())
326 }
327 check.errorf(obj.Pos(), "\t%s", obj.Name())
328
329 return true
330 }
331
332 func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
333 assert(obj.typ == nil)
334
335
336 check.iota = obj.val
337 defer func() { check.iota = nil }()
338
339
340 obj.val = constant.MakeUnknown()
341
342
343 if typ != nil {
344 t := check.typ(typ)
345 if !isConstType(t) {
346
347
348 if t.Underlying() != Typ[Invalid] {
349 check.errorf(typ.Pos(), "invalid constant type %s", t)
350 }
351 obj.typ = Typ[Invalid]
352 return
353 }
354 obj.typ = t
355 }
356
357
358 var x operand
359 if init != nil {
360 check.expr(&x, init)
361 }
362 check.initConst(obj, &x)
363 }
364
365 func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
366 assert(obj.typ == nil)
367
368
369 if typ != nil {
370 obj.typ = check.typ(typ)
371
372
373
374
375
376
377
378
379 }
380
381
382 if init == nil {
383 if typ == nil {
384
385 obj.typ = Typ[Invalid]
386 }
387 return
388 }
389
390 if lhs == nil || len(lhs) == 1 {
391 assert(lhs == nil || lhs[0] == obj)
392 var x operand
393 check.expr(&x, init)
394 check.initVar(obj, &x, "variable declaration")
395 return
396 }
397
398 if debug {
399
400 found := false
401 for _, lhs := range lhs {
402 if obj == lhs {
403 found = true
404 break
405 }
406 }
407 if !found {
408 panic("inconsistent lhs")
409 }
410 }
411
412
413
414
415
416 if typ != nil {
417 for _, lhs := range lhs {
418 lhs.typ = obj.typ
419 }
420 }
421
422 check.initVars(lhs, []ast.Expr{init}, token.NoPos)
423 }
424
425
426
427
428 func underlying(typ Type) Type {
429 for {
430 n, _ := typ.(*Named)
431 if n == nil {
432 break
433 }
434 typ = n.underlying
435 }
436 return typ
437 }
438
439 func (n *Named) setUnderlying(typ Type) {
440 if n != nil {
441 n.underlying = typ
442 }
443 }
444
445 func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, alias bool) {
446 assert(obj.typ == nil)
447
448 if alias {
449
450 obj.typ = Typ[Invalid]
451 obj.typ = check.typ(typ)
452
453 } else {
454
455 named := &Named{obj: obj}
456 def.setUnderlying(named)
457 obj.typ = named
458
459
460 check.definedType(typ, named)
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475 named.underlying = underlying(named.underlying)
476
477 }
478
479 check.addMethodDecls(obj)
480 }
481
482 func (check *Checker) addMethodDecls(obj *TypeName) {
483
484
485
486
487 methods := check.methods[obj]
488 if methods == nil {
489 return
490 }
491 delete(check.methods, obj)
492 assert(!check.objMap[obj].alias)
493
494
495 var mset objset
496
497
498
499 base, _ := obj.typ.(*Named)
500 if base != nil {
501 if t, _ := base.underlying.(*Struct); t != nil {
502 for _, fld := range t.fields {
503 if fld.name != "_" {
504 assert(mset.insert(fld) == nil)
505 }
506 }
507 }
508
509
510
511
512 for _, m := range base.methods {
513 assert(m.name != "_")
514 assert(mset.insert(m) == nil)
515 }
516 }
517
518
519 for _, m := range methods {
520
521
522 assert(m.name != "_")
523 if alt := mset.insert(m); alt != nil {
524 switch alt.(type) {
525 case *Var:
526 check.errorf(m.pos, "field and method with the same name %s", m.name)
527 case *Func:
528 check.errorf(m.pos, "method %s already declared for %s", m.name, obj)
529 default:
530 unreachable()
531 }
532 check.reportAltDecl(alt)
533 continue
534 }
535
536 if base != nil {
537 base.methods = append(base.methods, m)
538 }
539 }
540 }
541
542 func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
543 assert(obj.typ == nil)
544
545
546 assert(check.iota == nil)
547
548 sig := new(Signature)
549 obj.typ = sig
550 fdecl := decl.fdecl
551 check.funcType(sig, fdecl.Recv, fdecl.Type)
552 if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) {
553 check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
554
555 }
556
557
558
559 if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
560 check.later(func() {
561 check.funcBody(decl, obj.name, sig, fdecl.Body, nil)
562 })
563 }
564 }
565
566 func (check *Checker) declStmt(decl ast.Decl) {
567 pkg := check.pkg
568
569 switch d := decl.(type) {
570 case *ast.BadDecl:
571
572
573 case *ast.GenDecl:
574 var last *ast.ValueSpec
575 for iota, spec := range d.Specs {
576 switch s := spec.(type) {
577 case *ast.ValueSpec:
578 switch d.Tok {
579 case token.CONST:
580 top := len(check.delayed)
581
582
583 switch {
584 case s.Type != nil || len(s.Values) > 0:
585 last = s
586 case last == nil:
587 last = new(ast.ValueSpec)
588 }
589
590
591 lhs := make([]*Const, len(s.Names))
592 for i, name := range s.Names {
593 obj := NewConst(name.Pos(), pkg, name.Name, nil, constant.MakeInt64(int64(iota)))
594 lhs[i] = obj
595
596 var init ast.Expr
597 if i < len(last.Values) {
598 init = last.Values[i]
599 }
600
601 check.constDecl(obj, last.Type, init)
602 }
603
604 check.arityMatch(s, last)
605
606
607 check.processDelayed(top)
608
609
610
611
612
613 scopePos := s.End()
614 for i, name := range s.Names {
615 check.declare(check.scope, name, lhs[i], scopePos)
616 }
617
618 case token.VAR:
619 top := len(check.delayed)
620
621 lhs0 := make([]*Var, len(s.Names))
622 for i, name := range s.Names {
623 lhs0[i] = NewVar(name.Pos(), pkg, name.Name, nil)
624 }
625
626
627 for i, obj := range lhs0 {
628 var lhs []*Var
629 var init ast.Expr
630 switch len(s.Values) {
631 case len(s.Names):
632
633 init = s.Values[i]
634 case 1:
635
636 lhs = lhs0
637 init = s.Values[0]
638 default:
639 if i < len(s.Values) {
640 init = s.Values[i]
641 }
642 }
643 check.varDecl(obj, lhs, s.Type, init)
644 if len(s.Values) == 1 {
645
646
647
648
649
650 if debug {
651 for _, obj := range lhs0 {
652 assert(obj.typ != nil)
653 }
654 }
655 break
656 }
657 }
658
659 check.arityMatch(s, nil)
660
661
662 check.processDelayed(top)
663
664
665
666 scopePos := s.End()
667 for i, name := range s.Names {
668
669 check.declare(check.scope, name, lhs0[i], scopePos)
670 }
671
672 default:
673 check.invalidAST(s.Pos(), "invalid token %s", d.Tok)
674 }
675
676 case *ast.TypeSpec:
677 obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil)
678
679
680
681 scopePos := s.Name.Pos()
682 check.declare(check.scope, s.Name, obj, scopePos)
683
684 obj.setColor(grey + color(check.push(obj)))
685 check.typeDecl(obj, s.Type, nil, s.Assign.IsValid())
686 check.pop().setColor(black)
687 default:
688 check.invalidAST(s.Pos(), "const, type, or var declaration expected")
689 }
690 }
691
692 default:
693 check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
694 }
695 }
696
View as plain text