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