Source file
src/go/types/decl.go
1
2
3
4
5 package types
6
7 import (
8 "fmt"
9 "go/ast"
10 "go/constant"
11 "go/token"
12 . "internal/types/errors"
13 "slices"
14 )
15
16 func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object, pos token.Pos) {
17
18
19
20
21 if obj.Name() != "_" {
22 if alt := scope.Insert(obj); alt != nil {
23 err := check.newError(DuplicateDecl)
24 err.addf(obj, "%s redeclared in this block", obj.Name())
25 err.addAltDecl(alt)
26 err.report()
27 return
28 }
29 obj.setScopePos(pos)
30 }
31 if id != nil {
32 check.recordDef(id, obj)
33 }
34 }
35
36
37 func pathString(path []Object) string {
38 var s string
39 for i, p := range path {
40 if i > 0 {
41 s += "->"
42 }
43 s += p.Name()
44 }
45 return s
46 }
47
48
49
50 func (check *Checker) objDecl(obj Object, def *TypeName) {
51 if tracePos {
52 check.pushPos(atPos(obj.Pos()))
53 defer func() {
54
55 if p := recover(); p != nil {
56 panic(p)
57 }
58 check.popPos()
59 }()
60 }
61
62 if check.conf._Trace && obj.Type() == nil {
63 if check.indent == 0 {
64 fmt.Println()
65 }
66 check.trace(obj.Pos(), "-- checking %s (objPath = %s)", obj, pathString(check.objPath))
67 check.indent++
68 defer func() {
69 check.indent--
70 check.trace(obj.Pos(), "=> %s", obj)
71 }()
72 }
73
74
75
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 if _, ok := check.objPathIdx[obj]; ok {
104 switch obj := obj.(type) {
105 case *Const, *Var:
106 if !check.validCycle(obj) || obj.Type() == nil {
107 obj.setType(Typ[Invalid])
108 }
109 case *TypeName:
110 if !check.validCycle(obj) {
111 obj.setType(Typ[Invalid])
112 }
113 case *Func:
114 if !check.validCycle(obj) {
115
116
117
118
119 }
120 default:
121 panic("unreachable")
122 }
123
124 assert(obj.Type() != nil)
125 return
126 }
127
128 if obj.Type() != nil {
129 return
130 }
131
132
133
134 check.push(obj)
135 defer check.pop()
136
137 d, ok := check.objMap[obj]
138 assert(ok)
139
140
141 defer func(env environment) {
142 check.environment = env
143 }(check.environment)
144 check.environment = environment{scope: d.file, version: d.version}
145
146
147
148
149
150
151 switch obj := obj.(type) {
152 case *Const:
153 check.decl = d
154 check.constDecl(obj, d.vtyp, d.init, d.inherited)
155 case *Var:
156 check.decl = d
157 check.varDecl(obj, d.lhs, d.vtyp, d.init)
158 case *TypeName:
159
160 check.typeDecl(obj, d.tdecl, def)
161 check.collectMethods(obj)
162 case *Func:
163
164 check.funcDecl(obj, d)
165 default:
166 panic("unreachable")
167 }
168 }
169
170
171
172 func (check *Checker) validCycle(obj Object) (valid bool) {
173
174 if debug {
175 info := check.objMap[obj]
176 inObjMap := info != nil && (info.fdecl == nil || info.fdecl.Recv == nil)
177 isPkgObj := obj.Parent() == check.pkg.scope
178 if isPkgObj != inObjMap {
179 check.dump("%v: inconsistent object map for %s (isPkgObj = %v, inObjMap = %v)", obj.Pos(), obj, isPkgObj, inObjMap)
180 panic("unreachable")
181 }
182 }
183
184
185 start, found := check.objPathIdx[obj]
186 assert(found)
187 cycle := check.objPath[start:]
188 tparCycle := false
189 nval := 0
190 ndef := 0
191 loop:
192 for _, obj := range cycle {
193 switch obj := obj.(type) {
194 case *Const, *Var:
195 nval++
196 case *TypeName:
197
198
199
200 if check.inTParamList && isGeneric(obj.typ) {
201 tparCycle = true
202 break loop
203 }
204
205
206
207
208
209
210
211
212
213
214 var alias bool
215 if check.conf._EnableAlias {
216 alias = obj.IsAlias()
217 } else {
218 if d := check.objMap[obj]; d != nil {
219 alias = d.tdecl.Assign.IsValid()
220 } else {
221 alias = obj.IsAlias()
222 }
223 }
224 if !alias {
225 ndef++
226 }
227 case *Func:
228
229 default:
230 panic("unreachable")
231 }
232 }
233
234 if check.conf._Trace {
235 check.trace(obj.Pos(), "## cycle detected: objPath = %s->%s (len = %d)", pathString(cycle), obj.Name(), len(cycle))
236 if tparCycle {
237 check.trace(obj.Pos(), "## cycle contains: generic type in a type parameter list")
238 } else {
239 check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef)
240 }
241 defer func() {
242 if valid {
243 check.trace(obj.Pos(), "=> cycle is valid")
244 } else {
245 check.trace(obj.Pos(), "=> error: cycle is invalid")
246 }
247 }()
248 }
249
250
251 if tparCycle {
252 return true
253 }
254
255
256
257
258 if nval == len(cycle) {
259 return true
260 }
261
262
263
264
265 if nval == 0 && ndef > 0 {
266 return true
267 }
268
269 check.cycleError(cycle, firstInSrc(cycle))
270 return false
271 }
272
273
274 func (check *Checker) cycleError(cycle []Object, start int) {
275
276
277
278
279 name := func(obj Object) string {
280 return packagePrefix(obj.Pkg(), check.qualifier) + obj.Name()
281 }
282
283
284 obj := cycle[start]
285 tname, _ := obj.(*TypeName)
286 if tname != nil {
287 if check.conf._EnableAlias {
288 if a, ok := tname.Type().(*Alias); ok {
289 a.fromRHS = Typ[Invalid]
290 }
291 } else {
292 if tname.IsAlias() {
293 check.validAlias(tname, Typ[Invalid])
294 }
295 }
296 }
297
298
299 if len(cycle) == 1 {
300 if tname != nil {
301 check.errorf(obj, InvalidDeclCycle, "invalid recursive type: %s refers to itself", name(obj))
302 } else {
303 check.errorf(obj, InvalidDeclCycle, "invalid cycle in declaration: %s refers to itself", name(obj))
304 }
305 return
306 }
307
308 err := check.newError(InvalidDeclCycle)
309 if tname != nil {
310 err.addf(obj, "invalid recursive type %s", name(obj))
311 } else {
312 err.addf(obj, "invalid cycle in declaration of %s", name(obj))
313 }
314
315 for i := range cycle {
316 next := cycle[(start+i+1)%len(cycle)]
317 err.addf(obj, "%s refers to %s", name(obj), name(next))
318 obj = next
319 }
320 err.report()
321 }
322
323
324
325 func firstInSrc(path []Object) int {
326 fst, pos := 0, path[0].Pos()
327 for i, t := range path[1:] {
328 if cmpPos(t.Pos(), pos) < 0 {
329 fst, pos = i+1, t.Pos()
330 }
331 }
332 return fst
333 }
334
335 type (
336 decl interface {
337 node() ast.Node
338 }
339
340 importDecl struct{ spec *ast.ImportSpec }
341 constDecl struct {
342 spec *ast.ValueSpec
343 iota int
344 typ ast.Expr
345 init []ast.Expr
346 inherited bool
347 }
348 varDecl struct{ spec *ast.ValueSpec }
349 typeDecl struct{ spec *ast.TypeSpec }
350 funcDecl struct{ decl *ast.FuncDecl }
351 )
352
353 func (d importDecl) node() ast.Node { return d.spec }
354 func (d constDecl) node() ast.Node { return d.spec }
355 func (d varDecl) node() ast.Node { return d.spec }
356 func (d typeDecl) node() ast.Node { return d.spec }
357 func (d funcDecl) node() ast.Node { return d.decl }
358
359 func (check *Checker) walkDecls(decls []ast.Decl, f func(decl)) {
360 for _, d := range decls {
361 check.walkDecl(d, f)
362 }
363 }
364
365 func (check *Checker) walkDecl(d ast.Decl, f func(decl)) {
366 switch d := d.(type) {
367 case *ast.BadDecl:
368
369 case *ast.GenDecl:
370 var last *ast.ValueSpec
371 for iota, s := range d.Specs {
372 switch s := s.(type) {
373 case *ast.ImportSpec:
374 f(importDecl{s})
375 case *ast.ValueSpec:
376 switch d.Tok {
377 case token.CONST:
378
379 inherited := true
380 switch {
381 case s.Type != nil || len(s.Values) > 0:
382 last = s
383 inherited = false
384 case last == nil:
385 last = new(ast.ValueSpec)
386 inherited = false
387 }
388 check.arityMatch(s, last)
389 f(constDecl{spec: s, iota: iota, typ: last.Type, init: last.Values, inherited: inherited})
390 case token.VAR:
391 check.arityMatch(s, nil)
392 f(varDecl{s})
393 default:
394 check.errorf(s, InvalidSyntaxTree, "invalid token %s", d.Tok)
395 }
396 case *ast.TypeSpec:
397 f(typeDecl{s})
398 default:
399 check.errorf(s, InvalidSyntaxTree, "unknown ast.Spec node %T", s)
400 }
401 }
402 case *ast.FuncDecl:
403 f(funcDecl{d})
404 default:
405 check.errorf(d, InvalidSyntaxTree, "unknown ast.Decl node %T", d)
406 }
407 }
408
409 func (check *Checker) constDecl(obj *Const, typ, init ast.Expr, inherited bool) {
410 assert(obj.typ == nil)
411
412
413 defer func(iota constant.Value, errpos positioner) {
414 check.iota = iota
415 check.errpos = errpos
416 }(check.iota, check.errpos)
417 check.iota = obj.val
418 check.errpos = nil
419
420
421 obj.val = constant.MakeUnknown()
422
423
424 if typ != nil {
425 t := check.typ(typ)
426 if !isConstType(t) {
427
428
429 if isValid(t.Underlying()) {
430 check.errorf(typ, InvalidConstType, "invalid constant type %s", t)
431 }
432 obj.typ = Typ[Invalid]
433 return
434 }
435 obj.typ = t
436 }
437
438
439 var x operand
440 if init != nil {
441 if inherited {
442
443
444
445
446
447
448 check.errpos = atPos(obj.pos)
449 }
450 check.expr(nil, &x, init)
451 }
452 check.initConst(obj, &x)
453 }
454
455 func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
456 assert(obj.typ == nil)
457
458
459 if typ != nil {
460 obj.typ = check.varType(typ)
461
462
463
464
465
466
467
468
469 }
470
471
472 if init == nil {
473 if typ == nil {
474
475 obj.typ = Typ[Invalid]
476 }
477 return
478 }
479
480 if lhs == nil || len(lhs) == 1 {
481 assert(lhs == nil || lhs[0] == obj)
482 var x operand
483 check.expr(newTarget(obj.typ, obj.name), &x, init)
484 check.initVar(obj, &x, "variable declaration")
485 return
486 }
487
488 if debug {
489
490 if !slices.Contains(lhs, obj) {
491 panic("inconsistent lhs")
492 }
493 }
494
495
496
497
498
499 if typ != nil {
500 for _, lhs := range lhs {
501 lhs.typ = obj.typ
502 }
503 }
504
505 check.initVars(lhs, []ast.Expr{init}, nil)
506 }
507
508
509 func (check *Checker) isImportedConstraint(typ Type) bool {
510 named := asNamed(typ)
511 if named == nil || named.obj.pkg == check.pkg || named.obj.pkg == nil {
512 return false
513 }
514 u, _ := named.Underlying().(*Interface)
515 return u != nil && !u.IsMethodSet()
516 }
517
518 func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *TypeName) {
519 assert(obj.typ == nil)
520
521
522 versionErr := false
523
524 var rhs Type
525 check.later(func() {
526 if t := asNamed(obj.typ); t != nil {
527 check.validType(t)
528 }
529
530 _ = !versionErr && check.isImportedConstraint(rhs) && check.verifyVersionf(tdecl.Type, go1_18, "using type constraint %s", rhs)
531 }).describef(obj, "validType(%s)", obj.Name())
532
533
534 var tparam0 *ast.Field
535 if tdecl.TypeParams.NumFields() > 0 {
536 tparam0 = tdecl.TypeParams.List[0]
537 }
538
539
540 if tdecl.Assign.IsValid() {
541
542
543 if !versionErr && tparam0 != nil && !check.verifyVersionf(tparam0, go1_23, "generic type alias") {
544 versionErr = true
545 }
546 if !versionErr && !check.verifyVersionf(atPos(tdecl.Assign), go1_9, "type alias") {
547 versionErr = true
548 }
549
550 if check.conf._EnableAlias {
551 alias := check.newAlias(obj, nil)
552 setDefType(def, alias)
553
554
555
556 defer func() {
557 if alias.fromRHS == nil {
558 alias.fromRHS = Typ[Invalid]
559 unalias(alias)
560 }
561 }()
562
563
564 if tparam0 != nil {
565 check.openScope(tdecl, "type parameters")
566 defer check.closeScope()
567 check.collectTypeParams(&alias.tparams, tdecl.TypeParams)
568 }
569
570 rhs = check.declaredType(tdecl.Type, obj)
571 assert(rhs != nil)
572 alias.fromRHS = rhs
573
574
575
576 if tpar, ok := rhs.(*TypeParam); ok && alias.tparams != nil && slices.Index(alias.tparams.list(), tpar) >= 0 {
577 check.error(tdecl.Type, MisplacedTypeParam, "cannot use type parameter declared in alias declaration as RHS")
578 alias.fromRHS = Typ[Invalid]
579 }
580 } else {
581
582
583
584
585
586 gotypesalias.IncNonDefault()
587
588 if !versionErr && tparam0 != nil {
589 check.error(tdecl, UnsupportedFeature, "generic type alias requires GODEBUG=gotypesalias=1 or unset")
590 versionErr = true
591 }
592
593 check.brokenAlias(obj)
594 rhs = check.typ(tdecl.Type)
595 check.validAlias(obj, rhs)
596 }
597 return
598 }
599
600
601 if !versionErr && tparam0 != nil && !check.verifyVersionf(tparam0, go1_18, "type parameter") {
602 versionErr = true
603 }
604
605 named := check.newNamed(obj, nil, nil)
606 setDefType(def, named)
607
608
609
610
611
612
613
614
615
616
617 named.allowNilRHS = true
618 defer (func() { named.allowNilRHS = false })()
619
620 if tdecl.TypeParams != nil {
621 check.openScope(tdecl, "type parameters")
622 defer check.closeScope()
623 check.collectTypeParams(&named.tparams, tdecl.TypeParams)
624 }
625
626 rhs = check.declaredType(tdecl.Type, obj)
627 assert(rhs != nil)
628 named.fromRHS = rhs
629
630
631
632 if isTypeParam(rhs) {
633 check.error(tdecl.Type, MisplacedTypeParam, "cannot use a type parameter as RHS in type declaration")
634 named.fromRHS = Typ[Invalid]
635 }
636 }
637
638 func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList) {
639 var tparams []*TypeParam
640
641
642
643 scopePos := list.Pos()
644 for _, f := range list.List {
645 for _, name := range f.Names {
646 tparams = append(tparams, check.declareTypeParam(name, scopePos))
647 }
648 }
649
650
651
652
653 *dst = bindTParams(tparams)
654
655
656
657
658
659
660
661
662 assert(!check.inTParamList)
663 check.inTParamList = true
664 defer func() {
665 check.inTParamList = false
666 }()
667
668 index := 0
669 for _, f := range list.List {
670 var bound Type
671
672
673 if f.Type != nil {
674 bound = check.bound(f.Type)
675 if isTypeParam(bound) {
676
677
678
679
680 check.error(f.Type, MisplacedTypeParam, "cannot use a type parameter as constraint")
681 bound = Typ[Invalid]
682 }
683 } else {
684 bound = Typ[Invalid]
685 }
686 for i := range f.Names {
687 tparams[index+i].bound = bound
688 }
689 index += len(f.Names)
690 }
691 }
692
693 func (check *Checker) bound(x ast.Expr) Type {
694
695
696
697 wrap := false
698 switch op := x.(type) {
699 case *ast.UnaryExpr:
700 wrap = op.Op == token.TILDE
701 case *ast.BinaryExpr:
702 wrap = op.Op == token.OR
703 }
704 if wrap {
705 x = &ast.InterfaceType{Methods: &ast.FieldList{List: []*ast.Field{{Type: x}}}}
706 t := check.typ(x)
707
708 if t, _ := t.(*Interface); t != nil {
709 t.implicit = true
710 }
711 return t
712 }
713 return check.typ(x)
714 }
715
716 func (check *Checker) declareTypeParam(name *ast.Ident, scopePos token.Pos) *TypeParam {
717
718
719
720
721
722
723 tname := NewTypeName(name.Pos(), check.pkg, name.Name, nil)
724 tpar := check.newTypeParam(tname, Typ[Invalid])
725 check.declare(check.scope, name, tname, scopePos)
726 return tpar
727 }
728
729 func (check *Checker) collectMethods(obj *TypeName) {
730
731
732
733
734 methods := check.methods[obj]
735 if methods == nil {
736 return
737 }
738 delete(check.methods, obj)
739 assert(!check.objMap[obj].tdecl.Assign.IsValid())
740
741
742 var mset objset
743
744
745
746 base := asNamed(obj.typ)
747 if base != nil {
748 assert(base.TypeArgs().Len() == 0)
749
750
751
752 check.later(func() {
753 check.checkFieldUniqueness(base)
754 }).describef(obj, "verifying field uniqueness for %v", base)
755
756
757
758
759 for i := 0; i < base.NumMethods(); i++ {
760 m := base.Method(i)
761 assert(m.name != "_")
762 assert(mset.insert(m) == nil)
763 }
764 }
765
766
767 for _, m := range methods {
768
769
770 assert(m.name != "_")
771 if alt := mset.insert(m); alt != nil {
772 if alt.Pos().IsValid() {
773 check.errorf(m, DuplicateMethod, "method %s.%s already declared at %v", obj.Name(), m.name, alt.Pos())
774 } else {
775 check.errorf(m, DuplicateMethod, "method %s.%s already declared", obj.Name(), m.name)
776 }
777 continue
778 }
779
780 if base != nil {
781 base.AddMethod(m)
782 }
783 }
784 }
785
786 func (check *Checker) checkFieldUniqueness(base *Named) {
787 if t, _ := base.Underlying().(*Struct); t != nil {
788 var mset objset
789 for i := 0; i < base.NumMethods(); i++ {
790 m := base.Method(i)
791 assert(m.name != "_")
792 assert(mset.insert(m) == nil)
793 }
794
795
796
797 for _, fld := range t.fields {
798 if fld.name != "_" {
799 if alt := mset.insert(fld); alt != nil {
800
801
802 _ = alt.(*Func)
803
804
805
806 err := check.newError(DuplicateFieldAndMethod)
807 err.addf(alt, "field and method with the same name %s", fld.name)
808 err.addAltDecl(fld)
809 err.report()
810 }
811 }
812 }
813 }
814 }
815
816 func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
817 assert(obj.typ == nil)
818
819
820 assert(check.iota == nil)
821
822 sig := new(Signature)
823 obj.typ = sig
824
825 fdecl := decl.fdecl
826 check.funcType(sig, fdecl.Recv, fdecl.Type)
827
828
829
830 sig.scope.pos = fdecl.Pos()
831 sig.scope.end = fdecl.End()
832
833 if fdecl.Type.TypeParams.NumFields() > 0 && fdecl.Body == nil {
834 check.softErrorf(fdecl.Name, BadDecl, "generic function is missing function body")
835 }
836
837
838
839 if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
840 check.later(func() {
841 check.funcBody(decl, obj.name, sig, fdecl.Body, nil)
842 }).describef(obj, "func %s", obj.name)
843 }
844 }
845
846 func (check *Checker) declStmt(d ast.Decl) {
847 pkg := check.pkg
848
849 check.walkDecl(d, func(d decl) {
850 switch d := d.(type) {
851 case constDecl:
852 top := len(check.delayed)
853
854
855 lhs := make([]*Const, len(d.spec.Names))
856 for i, name := range d.spec.Names {
857 obj := NewConst(name.Pos(), pkg, name.Name, nil, constant.MakeInt64(int64(d.iota)))
858 lhs[i] = obj
859
860 var init ast.Expr
861 if i < len(d.init) {
862 init = d.init[i]
863 }
864
865 check.constDecl(obj, d.typ, init, d.inherited)
866 }
867
868
869 check.processDelayed(top)
870
871
872
873
874
875 scopePos := d.spec.End()
876 for i, name := range d.spec.Names {
877 check.declare(check.scope, name, lhs[i], scopePos)
878 }
879
880 case varDecl:
881 top := len(check.delayed)
882
883 lhs0 := make([]*Var, len(d.spec.Names))
884 for i, name := range d.spec.Names {
885 lhs0[i] = newVar(LocalVar, name.Pos(), pkg, name.Name, nil)
886 }
887
888
889 for i, obj := range lhs0 {
890 var lhs []*Var
891 var init ast.Expr
892 switch len(d.spec.Values) {
893 case len(d.spec.Names):
894
895 init = d.spec.Values[i]
896 case 1:
897
898 lhs = lhs0
899 init = d.spec.Values[0]
900 default:
901 if i < len(d.spec.Values) {
902 init = d.spec.Values[i]
903 }
904 }
905 check.varDecl(obj, lhs, d.spec.Type, init)
906 if len(d.spec.Values) == 1 {
907
908
909
910
911
912 if debug {
913 for _, obj := range lhs0 {
914 assert(obj.typ != nil)
915 }
916 }
917 break
918 }
919 }
920
921
922 check.processDelayed(top)
923
924
925
926 scopePos := d.spec.End()
927 for i, name := range d.spec.Names {
928
929 check.declare(check.scope, name, lhs0[i], scopePos)
930 }
931
932 case typeDecl:
933 obj := NewTypeName(d.spec.Name.Pos(), pkg, d.spec.Name.Name, nil)
934
935
936
937 scopePos := d.spec.Name.Pos()
938 check.declare(check.scope, d.spec.Name, obj, scopePos)
939 check.push(obj)
940 check.typeDecl(obj, d.spec, nil)
941 check.pop()
942 default:
943 check.errorf(d.node(), InvalidSyntaxTree, "unknown ast.Decl node %T", d.node())
944 }
945 })
946 }
947
View as plain text