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