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