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