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 if !tparCycle {
290
291
292
293 if nval == len(cycle) {
294 return true
295 }
296
297
298
299
300 if nval == 0 && ndef > 0 {
301 return true
302 }
303 }
304
305 check.cycleError(cycle, firstInSrc(cycle))
306 return false
307 }
308
309
310 func (check *Checker) cycleError(cycle []Object, start int) {
311
312
313
314
315 name := func(obj Object) string {
316 return packagePrefix(obj.Pkg(), check.qualifier) + obj.Name()
317 }
318
319
320 obj := cycle[start]
321 tname, _ := obj.(*TypeName)
322 if tname != nil {
323 if check.conf.EnableAlias {
324 if a, ok := tname.Type().(*Alias); ok {
325 a.fromRHS = Typ[Invalid]
326 }
327 } else {
328 if tname.IsAlias() {
329 check.validAlias(tname, Typ[Invalid])
330 }
331 }
332 }
333
334
335 if len(cycle) == 1 {
336 if tname != nil {
337 check.errorf(obj, InvalidDeclCycle, "invalid recursive type: %s refers to itself", name(obj))
338 } else {
339 check.errorf(obj, InvalidDeclCycle, "invalid cycle in declaration: %s refers to itself", name(obj))
340 }
341 return
342 }
343
344 err := check.newError(InvalidDeclCycle)
345 if tname != nil {
346 err.addf(obj, "invalid recursive type %s", name(obj))
347 } else {
348 err.addf(obj, "invalid cycle in declaration of %s", name(obj))
349 }
350
351 for i := range cycle {
352 next := cycle[(start+i+1)%len(cycle)]
353 err.addf(obj, "%s refers to %s", name(obj), name(next))
354 obj = next
355 }
356 err.report()
357 }
358
359
360
361 func firstInSrc(path []Object) int {
362 fst, pos := 0, path[0].Pos()
363 for i, t := range path[1:] {
364 if cmpPos(t.Pos(), pos) < 0 {
365 fst, pos = i+1, t.Pos()
366 }
367 }
368 return fst
369 }
370
371 func (check *Checker) constDecl(obj *Const, typ, init syntax.Expr, inherited bool) {
372 assert(obj.typ == nil)
373
374
375 defer func(iota constant.Value, errpos syntax.Pos) {
376 check.iota = iota
377 check.errpos = errpos
378 }(check.iota, check.errpos)
379 check.iota = obj.val
380 check.errpos = nopos
381
382
383 obj.val = constant.MakeUnknown()
384
385
386 if typ != nil {
387 t := check.typ(typ)
388 if !isConstType(t) {
389
390
391 if isValid(under(t)) {
392 check.errorf(typ, InvalidConstType, "invalid constant type %s", t)
393 }
394 obj.typ = Typ[Invalid]
395 return
396 }
397 obj.typ = t
398 }
399
400
401 var x operand
402 if init != nil {
403 if inherited {
404
405
406
407
408
409
410 check.errpos = obj.pos
411 }
412 check.expr(nil, &x, init)
413 }
414 check.initConst(obj, &x)
415 }
416
417 func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) {
418 assert(obj.typ == nil)
419
420
421 if typ != nil {
422 obj.typ = check.varType(typ)
423
424
425
426
427
428
429
430
431 }
432
433
434 if init == nil {
435 if typ == nil {
436
437 obj.typ = Typ[Invalid]
438 }
439 return
440 }
441
442 if lhs == nil || len(lhs) == 1 {
443 assert(lhs == nil || lhs[0] == obj)
444 var x operand
445 check.expr(newTarget(obj.typ, obj.name), &x, init)
446 check.initVar(obj, &x, "variable declaration")
447 return
448 }
449
450 if debug {
451
452 if !slices.Contains(lhs, obj) {
453 panic("inconsistent lhs")
454 }
455 }
456
457
458
459
460
461 if typ != nil {
462 for _, lhs := range lhs {
463 lhs.typ = obj.typ
464 }
465 }
466
467 check.initVars(lhs, []syntax.Expr{init}, nil)
468 }
469
470
471 func (check *Checker) isImportedConstraint(typ Type) bool {
472 named := asNamed(typ)
473 if named == nil || named.obj.pkg == check.pkg || named.obj.pkg == nil {
474 return false
475 }
476 u, _ := named.under().(*Interface)
477 return u != nil && !u.IsMethodSet()
478 }
479
480 func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *TypeName) {
481 assert(obj.typ == nil)
482
483
484 versionErr := false
485
486 var rhs Type
487 check.later(func() {
488 if t := asNamed(obj.typ); t != nil {
489 check.validType(t)
490 }
491
492 _ = !versionErr && check.isImportedConstraint(rhs) && check.verifyVersionf(tdecl.Type, go1_18, "using type constraint %s", rhs)
493 }).describef(obj, "validType(%s)", obj.Name())
494
495
496 var tparam0 *syntax.Field
497 if len(tdecl.TParamList) > 0 {
498 tparam0 = tdecl.TParamList[0]
499 }
500
501
502 if tdecl.Alias {
503
504
505 if !versionErr && tparam0 != nil && !check.verifyVersionf(tparam0, go1_23, "generic type alias") {
506 versionErr = true
507 }
508 if !versionErr && !check.verifyVersionf(tdecl, go1_9, "type alias") {
509 versionErr = true
510 }
511
512 if check.conf.EnableAlias {
513 alias := check.newAlias(obj, nil)
514 setDefType(def, alias)
515
516
517
518 defer func() {
519 if alias.fromRHS == nil {
520 alias.fromRHS = Typ[Invalid]
521 unalias(alias)
522 }
523 }()
524
525
526 if tparam0 != nil {
527 check.openScope(tdecl, "type parameters")
528 defer check.closeScope()
529 check.collectTypeParams(&alias.tparams, tdecl.TParamList)
530 }
531
532 rhs = check.definedType(tdecl.Type, obj)
533 assert(rhs != nil)
534
535 alias.fromRHS = rhs
536 unalias(alias)
537 } else {
538 if !versionErr && tparam0 != nil {
539 check.error(tdecl, UnsupportedFeature, "generic type alias requires GODEBUG=gotypesalias=1 or unset")
540 versionErr = true
541 }
542
543 check.brokenAlias(obj)
544 rhs = check.typ(tdecl.Type)
545 check.validAlias(obj, rhs)
546 }
547 return
548 }
549
550
551 if !versionErr && tparam0 != nil && !check.verifyVersionf(tparam0, go1_18, "type parameter") {
552 versionErr = true
553 }
554
555 named := check.newNamed(obj, nil, nil)
556 setDefType(def, named)
557
558 if tdecl.TParamList != nil {
559 check.openScope(tdecl, "type parameters")
560 defer check.closeScope()
561 check.collectTypeParams(&named.tparams, tdecl.TParamList)
562 }
563
564
565 rhs = check.definedType(tdecl.Type, obj)
566 assert(rhs != nil)
567 named.fromRHS = rhs
568
569
570
571 if named.underlying == nil {
572 named.underlying = Typ[Invalid]
573 }
574
575
576
577
578
579
580 if isTypeParam(rhs) {
581 check.error(tdecl.Type, MisplacedTypeParam, "cannot use a type parameter as RHS in type declaration")
582 named.underlying = Typ[Invalid]
583 }
584 }
585
586 func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Field) {
587 tparams := make([]*TypeParam, len(list))
588
589
590
591
592 if len(list) > 0 {
593 scopePos := list[0].Pos()
594 for i, f := range list {
595 tparams[i] = check.declareTypeParam(f.Name, scopePos)
596 }
597 }
598
599
600
601
602 *dst = bindTParams(tparams)
603
604
605
606
607
608
609
610
611 assert(!check.inTParamList)
612 check.inTParamList = true
613 defer func() {
614 check.inTParamList = false
615 }()
616
617
618 var bound Type
619 for i, f := range list {
620
621
622
623 if i == 0 || f.Type != list[i-1].Type {
624 bound = check.bound(f.Type)
625 if isTypeParam(bound) {
626
627
628
629
630 check.error(f.Type, MisplacedTypeParam, "cannot use a type parameter as constraint")
631 bound = Typ[Invalid]
632 }
633 }
634 tparams[i].bound = bound
635 }
636 }
637
638 func (check *Checker) bound(x syntax.Expr) Type {
639
640
641
642 if op, _ := x.(*syntax.Operation); op != nil && (op.Op == syntax.Tilde || op.Op == syntax.Or) {
643 t := check.typ(&syntax.InterfaceType{MethodList: []*syntax.Field{{Type: x}}})
644
645 if t, _ := t.(*Interface); t != nil {
646 t.implicit = true
647 }
648 return t
649 }
650 return check.typ(x)
651 }
652
653 func (check *Checker) declareTypeParam(name *syntax.Name, scopePos syntax.Pos) *TypeParam {
654
655
656
657
658
659
660 tname := NewTypeName(name.Pos(), check.pkg, name.Value, nil)
661 tpar := check.newTypeParam(tname, Typ[Invalid])
662 check.declare(check.scope, name, tname, scopePos)
663 return tpar
664 }
665
666 func (check *Checker) collectMethods(obj *TypeName) {
667
668
669
670
671 methods := check.methods[obj]
672 if methods == nil {
673 return
674 }
675 delete(check.methods, obj)
676 assert(!check.objMap[obj].tdecl.Alias)
677
678
679 var mset objset
680
681
682
683 base := asNamed(obj.typ)
684 if base != nil {
685 assert(base.TypeArgs().Len() == 0)
686
687
688
689 check.later(func() {
690 check.checkFieldUniqueness(base)
691 }).describef(obj, "verifying field uniqueness for %v", base)
692
693
694
695
696 for i := 0; i < base.NumMethods(); i++ {
697 m := base.Method(i)
698 assert(m.name != "_")
699 assert(mset.insert(m) == nil)
700 }
701 }
702
703
704 for _, m := range methods {
705
706
707 assert(m.name != "_")
708 if alt := mset.insert(m); alt != nil {
709 if alt.Pos().IsKnown() {
710 check.errorf(m.pos, DuplicateMethod, "method %s.%s already declared at %v", obj.Name(), m.name, alt.Pos())
711 } else {
712 check.errorf(m.pos, DuplicateMethod, "method %s.%s already declared", obj.Name(), m.name)
713 }
714 continue
715 }
716
717 if base != nil {
718 base.AddMethod(m)
719 }
720 }
721 }
722
723 func (check *Checker) checkFieldUniqueness(base *Named) {
724 if t, _ := base.under().(*Struct); t != nil {
725 var mset objset
726 for i := 0; i < base.NumMethods(); i++ {
727 m := base.Method(i)
728 assert(m.name != "_")
729 assert(mset.insert(m) == nil)
730 }
731
732
733
734 for _, fld := range t.fields {
735 if fld.name != "_" {
736 if alt := mset.insert(fld); alt != nil {
737
738
739 _ = alt.(*Func)
740
741
742
743 err := check.newError(DuplicateFieldAndMethod)
744 err.addf(alt, "field and method with the same name %s", fld.name)
745 err.addAltDecl(fld)
746 err.report()
747 }
748 }
749 }
750 }
751 }
752
753 func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
754 assert(obj.typ == nil)
755
756
757 assert(check.iota == nil)
758
759 sig := new(Signature)
760 obj.typ = sig
761
762
763
764
765
766
767
768 saved := obj.color_
769 obj.color_ = black
770 fdecl := decl.fdecl
771 check.funcType(sig, fdecl.Recv, fdecl.TParamList, fdecl.Type)
772 obj.color_ = saved
773
774
775
776 sig.scope.pos = fdecl.Pos()
777 sig.scope.end = syntax.EndPos(fdecl)
778
779 if len(fdecl.TParamList) > 0 && fdecl.Body == nil {
780 check.softErrorf(fdecl, BadDecl, "generic function is missing function body")
781 }
782
783
784
785 if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
786 check.later(func() {
787 check.funcBody(decl, obj.name, sig, fdecl.Body, nil)
788 }).describef(obj, "func %s", obj.name)
789 }
790 }
791
792 func (check *Checker) declStmt(list []syntax.Decl) {
793 pkg := check.pkg
794
795 first := -1
796 var last *syntax.ConstDecl
797 for index, decl := range list {
798 if _, ok := decl.(*syntax.ConstDecl); !ok {
799 first = -1
800 }
801
802 switch s := decl.(type) {
803 case *syntax.ConstDecl:
804 top := len(check.delayed)
805
806
807 if first < 0 || s.Group == nil || list[index-1].(*syntax.ConstDecl).Group != s.Group {
808 first = index
809 last = nil
810 }
811 iota := constant.MakeInt64(int64(index - first))
812
813
814 inherited := true
815 switch {
816 case s.Type != nil || s.Values != nil:
817 last = s
818 inherited = false
819 case last == nil:
820 last = new(syntax.ConstDecl)
821 inherited = false
822 }
823
824
825 lhs := make([]*Const, len(s.NameList))
826 values := syntax.UnpackListExpr(last.Values)
827 for i, name := range s.NameList {
828 obj := NewConst(name.Pos(), pkg, name.Value, nil, iota)
829 lhs[i] = obj
830
831 var init syntax.Expr
832 if i < len(values) {
833 init = values[i]
834 }
835
836 check.constDecl(obj, last.Type, init, inherited)
837 }
838
839
840 check.arity(s.Pos(), s.NameList, values, true, inherited)
841
842
843 check.processDelayed(top)
844
845
846
847
848
849 scopePos := syntax.EndPos(s)
850 for i, name := range s.NameList {
851 check.declare(check.scope, name, lhs[i], scopePos)
852 }
853
854 case *syntax.VarDecl:
855 top := len(check.delayed)
856
857 lhs0 := make([]*Var, len(s.NameList))
858 for i, name := range s.NameList {
859 lhs0[i] = newVar(LocalVar, name.Pos(), pkg, name.Value, nil)
860 }
861
862
863 values := syntax.UnpackListExpr(s.Values)
864 for i, obj := range lhs0 {
865 var lhs []*Var
866 var init syntax.Expr
867 switch len(values) {
868 case len(s.NameList):
869
870 init = values[i]
871 case 1:
872
873 lhs = lhs0
874 init = values[0]
875 default:
876 if i < len(values) {
877 init = values[i]
878 }
879 }
880 check.varDecl(obj, lhs, s.Type, init)
881 if len(values) == 1 {
882
883
884
885
886
887 if debug {
888 for _, obj := range lhs0 {
889 assert(obj.typ != nil)
890 }
891 }
892 break
893 }
894 }
895
896
897 if s.Type == nil || values != nil {
898 check.arity(s.Pos(), s.NameList, values, false, false)
899 }
900
901
902 check.processDelayed(top)
903
904
905
906 scopePos := syntax.EndPos(s)
907 for i, name := range s.NameList {
908
909 check.declare(check.scope, name, lhs0[i], scopePos)
910 }
911
912 case *syntax.TypeDecl:
913 obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Value, nil)
914
915
916
917 scopePos := s.Name.Pos()
918 check.declare(check.scope, s.Name, obj, scopePos)
919
920 obj.setColor(grey + color(check.push(obj)))
921 check.typeDecl(obj, s, nil)
922 check.pop().setColor(black)
923
924 default:
925 check.errorf(s, InvalidSyntaxTree, "unknown syntax.Decl node %T", s)
926 }
927 }
928 }
929
View as plain text